LeetCode编程题(Java)---001 求数组中只出现一次的数字

前言

最近偶然听说LeetCode 这个网站有大把的编程题,按捺不住自己想要被虐的冲动,决定写下这个专栏,分享一些题目的最佳解题思路,当然解题思路可能是借鉴别人的,我只是记录下自己的心得,共勉!

题目赏析

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

要求:
不使用额外的存储空间

示例 1:

输入: [2,2,1]
输出: 1

示例 2:

输入: [4,1,2,1,2]
输出: 4

解题思路

1)不考虑题目的要求,使用集合工具类来解题

  • 建立一个 HashSet 集合
  • 遍历传入的数组,如果在集合中不存在当前遍历的数据,就存进集合中,如果发现相同的数据就移除原先进入集合的数据
  • 最终集合中剩下的数据,就是我们需要的结果
  • 如果集合为空,则说明该数组中全是重复的数据或者重复的次数全是两次,暂时不考虑数据重复次数为奇数次的情况
    示例代码
// 请忽略掉函数名字
 public static int getSingleNumber(int[] arr) {
    	if(arr.length == 0) { // 数组不能为空 这里我随意抛了个异常
    		throw new RuntimeException("数组不能为空");
    	}
    	// 新建一个HashSet 集合 用于存储我们需要的结果
    	Set<Integer> singleSet = new HashSet<>();
    	
    	// 遍历数组
    	for(int i=0;i<arr.length;i++) {
    		// 如果集合包含该元素  就移除当前元素 (也就是说重复了就把数据移出容器)
    		if(singleSet.contains(arr[i])) {
    			singleSet.remove(arr[i]);
    			// 移除重复数据后 继续执行循环
    			continue;
    		}
    		// 如果不包含该元素就放入到set集合中
    		singleSet.add(arr[i]);
    	}
    	// 根据题意最终只会存在一个单独的数据 所以使用迭代器取出数据即可
    	return singleSet.iterator().next();
    }

测试用例和结果

int[] arr = {2,3,4,4,2,3,1};

获取得数组中的唯一数据为:1

为什么选用HashSet 集合你们可以思考一下下哦!

2)考虑题目要求不适用额外的存储空间

首先我们需要复习一下知识点,^ 这个位操作符大家应该都熟悉吧,0 0 变 0, 1 1 变 0,0 1 变 1, 1 0 变 1, 魔术戏法谁用谁知道
接下来让我们来分析一下 ^ (异或操作符)的一个重要的特性

假设:a = 10 其二进制表示为 1010 (为了方便分析我们只取低四位), b = 5 二进制为 0101
现在我们有一个中间变量 c。
1) c = a ^ b = 1010 ^ 0101 = 1111; 
2) c ^ b = 1111 ^ 0101 = 1010 --> 最终结果 == a.

从上面的例子可以看出,一个数同另一个数异或两次,会得到其本身。
我们可以将这个特性代入题目中,可以看到题目中数组内部重复的数刚好是两个,至此天时地利人和完备了,解题思路飞出来了,不说了上代码:

/** 惊不惊喜?意不意外?这就是编程的魅力,这么简单几句代码就可以解决一个问题,足够优雅
public static int singleNumber(int[] nums) {
// 初始化最终结果 ,假定第一个数是最终结果
		int result = nums[0];
		// 遍历数组 无限异或直到遍历完毕
        for(int i = 1;i<nums.length;i++){
			result ^= nums[i];
        }
        // 异或特性 重复的全部消除
        return result;
    }

用例就不上了,肯定对的,这是官方公认的最佳解决方案,确实厉害呀!而且使用位操作符最大化了计算机的计算能力,努力学习吧,路还很长鸭!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值