题一:二叉树的序列化
假设有一颗二叉树,节点值为int值,用先旭遍历的方式序列化他,并且反序列化。
假设序列化后的结果为string,开始时string为“”;
先序遍历在遇到节点为null时就在string后面添加“#!”;
如果遇到非空节点假设节点值为val,那么就在后面添加“val!”。
反序列化的时候直接翻过来就行。
但是先序遍历序列化就要用先序遍历反序列化。
题二:
有一个整型数组A,其中只有一个数出现了奇数次,其他的数都出现了偶数次,请打印这个数。要求时间复杂度为O(N),额外空间复杂度为O(1)。
给定整形数组A及它的大小n,请返回题目所求数字。
分析:
n^0=n
n^n=0
所以该题的思路就是将所有的数组元素异或最终就会只剩一个奇数次出现的那个数。
题三:
给定一个整型数组arr,其中有两个数出现了奇数次,其他的数都出现了偶数次,找到这两个数。要求时间复杂度为O(N),额外空间复杂度为O(1)。
给定一个整形数组arr及它的大小n,请返回一个数组,其中两个元素为两个出现了奇数次的元素,请将他们按从小到大排列。
测试样例:
分析:
有上面的异或思路可以解此题
首先将数组的数挨个异或一遍最终肯定会得到奇数次出现的那个两个数(a,b)的异或结果设e0=a^b,那么而且e0一定不为0,那么我们就从右往左依次去找e0中第一个为1的为设为第k位,所以一定存在a、b中的某一个的第k位有且只有一个为1,设a的第k位位1,那么一次将数组中第k位位1的数依次又异或那么一定能得到a,因为在数组中第k位为1的数中只有a是出现了奇数次,再让a^e0即有a^a^b=b;所以就求出来了。
import java.util.*;
public class OddAppearance {
public int[] findOdds(int[] arr, int n) {
int e0=0;
for(int i=0;i<arr.length;i++){
e0^=arr[i];
}
int pos=0;
while(((e0>>pos)&1)!=1){
pos++;
}
int e1=0;
for(int i=0;i<arr.length;i++){
if(((arr[i]>>pos)&1)==1){
e1^=arr[i];
}
}
int min=Math.min(e1,e1^e0);
int max=Math.max(e1,e1^e0);
return new int[]{min,max};
}
}
题四:
对于两个32位整数a和b,请设计一个算法返回a和b中较大的。但是不能用任何比较判断。若两数相同,返回任意一个。
给定两个整数a和b,请返回较大的数。
解析:我也没太懂
import java.util.*;
public class Compare {
public int flip(int n) {//反转函数将1转化为0,0转化为1
return n ^ 1;
}
public int sign(int n) {//返回n的符号位
return flip((n >> 31) & 1);
}
public int getMax(int a, int b) {
int c = a - b;
int sa = sign(a);//a的符号位,整数返回1
int sb = sign(b);//b的符号位,,整数返回1
int sc = sign(c);//c的符号位,整数返回1
int difSab = sa ^ sb;//a、b是否异号,异号返回1
int sameSab = flip(difSab);//a、b是否同号,同号返回1
int returnA = difSab * sa + sameSab * sc;//不懂
int returnB = flip(returnA);
return a * returnA + b * returnB;
}
}