您的位置:首页 > 其它

leetcode--single_number&&single_number_II

2016-11-19 21:52 351 查看

single_number

题意: 给定一个整数类型数组,除了一个元素之外其他所有元素均出现两次,找出这个唯一的元素。

条件: 要求线性时间复杂度,并且不适用额外空间

分析: 本题非常经典,在《剑指offer》中也出现过,用到的方法是位运算中的异或操作。记录每一bit出现的次数。由于两个相同的整数做异或一定是0,所以数组中重复的整数异或之后也是0,遍历数组时两两异或,最后异或后的结果就是那个唯一值。(该方法非常经典,要牢记)

代码

public int singleNumber(int[] A) {
if(A == null){
return Integer.MIN_VALUE;
}else{
int length = A.length;
int result = 0;
for(int i = 0; i < length; i++){
result ^= A[i];
}
return result;
}
}


源程序下载

single_number_II

题意: 给定一个整数类型数组,除了一个元素之外其他所有元素均出现三次,找出这个唯一的元素。

条件: 要求线性时间复杂度,并且不适用额外空间

分析: 由于本题重复值出现三次,不能直接使用异或操作。既然一个二进制位不够,那我们不妨用两个二进制位来表示出现次数。为此,定义几个变量one, two, three, one表示某个位只出现一次,two 表示某个位出现过两次,three=one &two ,three 主要用来归零,只要出现过三次,就将one 和two改为0(和single_number不同的是,single_number出现两次就归零,所以异或可以完成,single_number_II出现三次归零)。最后返回one 即可。(该方法同样非常巧妙,抓住了该题的本质)

代码

public int singleNumber(int[] A) {
if(A == null){
return Integer.MIN_VALUE;
}else{
int one = 0;    //出现过一次的位
int two = 0;    //出现过两次的位
int three = 0;  //出现过三次的位
for(int i = 0; i < A.length; i++){
int a = A[i];
two |= one&a;   //先修改two
one ^= a;       //再修改one
three = one&two;    //one和two相应位置都是1的表示出现过3次
one &= ~three;     //出现过3次的位在one和two中都修正回0
two &= ~three;
}
return one;
}
}


源程序下载

single_number改

题意: 给定一个整数类型数组,除了两个元素之外其他所有元素均出现两次,找出这个唯一的元素。本题将只有一个唯一的编程有两个唯一的,其余均出现过两次

分析: 本题依然先用异或,但是异或后的结果是两个数叠加后的值,这该如何求解?异或后的结果是一个32位的整数(JAVA中int是32位),从最后一位开始向左找到第一个1出现的位置,那么这两个数在该位(bit)上的值一定不同(否则就变为0),那么可以根据这一位是0或者1将数组一分为二,前一个数组在该位上均是0,后一个数组载该位上均是1; 两个唯一的值肯定一个在前一个数组中,一个在后一个中。然后分别对两个数组求异或,两个数组中的唯一值都只有一个了,就变成single_number问题了!(how unimaginable we can solve problem use this way, and it is crazy who can come up with this settlement!),原谅我自己也没实现这个方法,读者自行解决吧~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  位运算 leetcode