【剑指 Offer 56 - I. 数组中数字出现的次数 中等】【剑指 Offer 56 - II. 数组中数字出现的次数 II 中等】
【剑指 Offer 56 - I. 数组中数字出现的次数 中等】
1. 题目描述
一个整型数组 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]
2. 思路
如果对于一个数组,除了【一个】数字之外,其余全都两两成对,那么所有数字异或得到的结果就是那个只出现一次的数字。回到这个题上,如果有两个数字只出现一次,所有数字的异或结果就是这两个数字的异或结果。我们找到这个异或结果中,第一位不为0的bit,按照这个bit是否为0,将nums分成两组,那么每一组都恰好有一个只出现一次的数字,并且其余的数因为成对出现也是只能出现在其中一组。
3. 代码
class Solution { public: int findFirstNonZeroPos(int num) { int index = 0; while( (num&1) != 1 && index < 32) { index ++; num = num >>1; } return index; } bool judgePosBitOne(int num, int index) { while(index > 0) { num = num >> 1; --index; } return (num &1) == 1; } vector<int> singleNumbers(vector<int>& nums) { int len = nums.size(); vector<int> res(2); if(len < 2) return nums; int XORRes = 0; for(int i = 0; i < len ;i ++) XORRes ^= nums[i]; int nonZeroBitPos = findFirstNonZeroPos(XORRes); int XORRes1 = 0, XORRes2 = 0; for(int i = 0; i < len; i++) { if(judgePosBitOne(nums[i], nonZeroBitPos)) { XORRes1 ^= nums[i]; } else { XORRes2 ^= nums[i]; } } res[0] = XORRes1; res[1] = XORRes2; return res; } };
【剑指 Offer 56 - II. 数组中数字出现的次数 II 中等】
1. 题目描述
在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。
示例 1:
输入:nums = [3,4,3,3]
输出:4
示例 2:
输入:nums = [9,1,7,9,7,9,7]
输出:1
2. 思路
若把所有数字的二进制表示,对应位的值相加,再将对应位的值%3,得到的值(0或者1)就是只出现一次的那个数字的对应二进制位的值。
3. 代码
class Solution { public: int singleNumber(vector<int>& nums) { int len = nums.size(); if(len < 4) return 0; int count[32] = {0}; for(int i = 0; i < len; i++) { for(int j = 0; j < 32; j++) { count[j] += nums[i] & 1; nums[i] = nums[i] >> 1; } } int res = 0; for(int i = 31; i >= 0; i--) { res = res<<1; int bit = count[i] % 3; res = res|bit; } return res; } };