题目
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例1
输入: [2,2,1]
输出: 1
示例2
输入: [4,1,2,1,2]
输出: 4
难度系数: 简单
解题思路一
常规方法是,遍历数组,然后统计每个值出现的次数,最后在选择出现次数为1的那个值.该算法的时间复杂度为O(N),首先是统计数组,此时要遍历整个数组,然后是要遍历我们的统计数组,此时有事一个O(N),由于我们使用了一个统计数组来保存每个值出现的次数,此时需要的空间复杂度为O(n),因此不符合要求.
解题思路二
为了解决不需要额外的空间这个要求,我们可以使用位操作中的异或规则来进行处理.异或运算法则如下
- a a = 0, a 0=a
- a b = b a
- a b c = a (b c) = a (c b) = (a b) c
其中,第一条规则说明,当某个数出现两次时,通过 变为0,出现一次时依然保持原来的数,第二、三条的交换律和分配律说明通过多次 操作最终解决本题。
注意: 本体题目中指出除了某个元素值出现一次外其余的均出现两次,根据法则一可以看出本算法只适合除了某个元素出现一次外,其余元素出现偶数次的情况。
比如在示例二中的 操作:
Java实现代码
/**
* @author Maosong Ran
* @date 2018/10/06
* @email maosongran@gmail.com
*/
public class LeetCode_136 {
public int singleNumber(int[] nums) {
int result = 0;
int len = nums.length;
for (int i=0; i < len; ++i)
result ^= nums[i];
return result;
}
public static void main(String[] args) {
LeetCode_136 leetCode = new LeetCode_136();
System.out.println(leetCode.singleNumber(new int[]{2, 2, 1}));
System.out.println(leetCode.singleNumber(new int[]{4, 1, 2, 1, 2}));
}
}
输出:
1
4