在java中,我几乎没有使用过位运算辅助算法,但是今天在leetcode上做了一个题,在自己用各种办法写出了程序测试成功之后,发现discuss中很多人都使用了位运算,高效简洁。
题目是这样的:给定一个整数数组,数组中的数都是成对出现,除了1个,找到这个数吧~(Given an array of integers, every element appears twice except for one. Find that single one.)
我的n种办法:
1.排序+遍历
public int singleNumber(int[] nums) {
Arrays.sort(nums);//排序
for(int i=1;i<nums.length-2;i++){
if(nums[i]!=nums[i-1] && nums[i]!=nums[i+1]) return nums[i];//判断这个数和前后是否相同,不同就把它揪出来
}
return nums.length==1?nums[0]:(nums[0]==nums[1]?nums[nums.length-1]:nums[0]);//没有找到说明是只有1个元素,或者不止一个元素,只有1个元素的话就是它,不<span style="white-space:pre"> </span>//止一个的话判断一下是第一个还是最后一个
}
leetcode显示的时间是404ms,java中算中间速度,比起c,c++,python,js等倒是差远了。。。可是判断很多,还要排序,很麻烦。
2.HashSet,用时420ms
public int singleNumber2(int[] nums){
HashSet<Integer> set=new HashSet<Integer>();
int count=0;
while(count<nums.length){
if(!set.contains(nums[count])){//如果set中没有这个元素,说明第一次遇到
set.add(nums[count]);//添加到set中
}else{
set.remove(nums[count]); //如果已经有这个元素了,那把这个元素移掉,最后set中将只剩下单着的那个数
}
count++;
}
Iterator it=set.iterator();//可是要把set中的元素取出来很麻烦啊,还得用迭代器,明明只有一个元素啊
while(it.hasNext()){
return (int) it.next();//取出元素
}
return nums[0];//如果上面的都不行,说明只有一个元素,返回数组的第一个。。。
}
这种更麻烦了,用到集合,迭代各种,最开始想用ArrayList,可是ArrayList有一个问题,因为元素是int类型,list.remove()这个方法,参数也同样是int类型,直接写
list.remove(nums[i]),会报错,原因是它寻找第nums[i]个元素,找的是下标而不是元素值。set相比于它就是无序,所以按值查找,list有序,按下标查找,这也导致了list取出元素可以直接根据索引,而set只能通过迭代器,for...each等结构。
3.Stack栈,用时456ms
public int singleNumber(int[] nums) {
Arrays.sort(nums);
Stack<Integer> stack=new Stack<Integer>();
int p=0;
while(p<nums.length){
if(stack.isEmpty()) stack.push(nums[p]);//空的,进栈
else if(stack.peek()==nums[p]) {
stack.pop();//当前这个和栈顶相同,出栈
}
else return nums[p-1];
p++;
}
return nums.length==1?nums[0]:nums[nums.length-1];
}
6到不行的版本(https://leetcode.com/discuss/28598/maybe-the-shortest-java-solution)
public int singleNumber4(int[] nums){
int a=0;
//for...each循环不是按位置,而是按元素
for(int i:nums){
a^=i;//a=a^i异或 按位相同取0,不同取1
}
return a;
}
点击打开链接