题目:一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
题目分析:
Java代码:
import java.util.Arrays;
/**
* 面试题56 - I. 数组中数字出现的次数
* 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。
* 要求时间复杂度是O(n),空间复杂度是O(1)。
*
* 示例 1:
* 输入:nums = [4,1,4,6]
* 输出:[1,6] 或 [6,1]
*
* 示例 2:
* 输入:nums = [1,2,10,4,1,4,3,3]
* 输出:[2,10] 或 [10,2]
*/
public class Offer56_I {
public static int[] singleNumbers(int[] nums) {
// 遍历数组中所有元素,进行异或,得到单独出现一次的两个数据的异或值。
int xor = 0;
for (int t: nums) {
xor ^= t;
}
// 获取到异或值的最低位的1所表示的数值。
// n&-n是求一个二进制数的最低位的1对应的数。 !!!
int flag = xor & (-xor);
// 该位的异或值为1,说明肯定一方为0,一方为1,因此可以通过逻辑与操作,将这两个数区分。
int ans1 = 0;
int ans2 = 0;
for (int temp:nums) {
// 逻辑与操作仅有两种结果,要么等于0,要么等于flag本身
if ((temp&flag)==0){
ans1 ^= temp;
}else {
ans2 ^= temp;
}
}
return new int[]{ans1, ans2};
}
public static void main(String[] args) {
int[] nums1 = {0,3,10,4,0,4,3,6,7,7,43,34,43,34,6,9}; // 10,9
int[] nums2 = {1,1,8,8,4,4,6,6,7,7,3,15}; // 3,15
int[] nums3 = {9,9,8,8,0,0,1,1,6,6,4,3}; // 4,3
int[] nums4 = {88,77,11,33,55,11,55,96,69,96,69,24, 88, 77}; // 33 24
int[] nums5 = {84,48,84,48,75,59,95,59}; // 75,95
System.out.println(Arrays.toString(singleNumbers(nums1)));
System.out.println(Arrays.toString(singleNumbers(nums2)));
System.out.println(Arrays.toString(singleNumbers(nums3)));
System.out.println(Arrays.toString(singleNumbers(nums4)));
System.out.println(Arrays.toString(singleNumbers(nums5)));
}
}
【注】
(1):leetcode 等平台只要我们完成一个函数即可,本人初出茅庐,为了巩固基本知识,故自己补充了部分代码,用于练手。本代码也许存在漏洞,望高手赐教。感谢!