算法之神奇的位运算

在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;
	}
点击打开链接




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值