day22
关于异或:1.任何数和0异或都等于那个数本身(a^0 = a),因为 0^1 = 1, 0^0 = 0
2.任何数和1异或都相当于按位取反,因为 1^1 = 0, 1^0 = 1
3.“还原性”(ps:个人理解):
举个栗子~ :A^B^A= B : A^B = m,m^A = B(m第二次异或同一个数(B)时会被还原成 之前还没有异或这个数(B)时的样子)
再来个实例:3^4^4 = 3 : 011 ^ 100 = 111,111 ^ 100 = 011(还原啦~)
1.剑指 Offer 56 - I. 数组中数字出现的次数
难点:分离 res 为 x和y
找到res中第一个为1的那位(8、9行),比如res = 10110,(低位开始)第二位处即为我们要找的,如何找:令m = 1(00001),res & m = 0,继续m = m << 1 =00010,res & m = 1(找到了我们要求的位置,退出循环) // m具有记录作用(记录res二进制码中某一位为1),用于区分两组数据
当res二进制码某一位为1时,x和y二进制码同一位置的数字应一个为0,一个为1(这样二者异或才为1)。根据这一区别将数组分为两组,每一组相当于求“数组中只出现一次的数字”,如此 x和y就求出来了
其实并不一定要求找res二进制码中第一个为1的那一位,随便找res二进制码中为1的一位 将数组分为两组数据即可。因为只有两个数字是只出现了一次 已经分别分到了两组中的一组,剩下的数都是出现了两次的,相同的两个数二进制码都相同 自然会被分到同一组,所以为什么说 “ 每一组相当于求“数组中只出现一次的数字” ”
= 1 class Solution { 2 public: 3 vector<int> singleNumbers(vector<int>& nums) { 4 int res = 0; 5 for(auto n : nums) 6 res ^= n; 7 int m = 1; 8 while((res & m) == 0) //& 优先级高于 == 9 m <<= 1; 10 int x =0,y = 0; 11 for(auto n : nums){ 12 if((n & m) == 0) 13 x ^= n; 14 else 15 y ^= n; 16 } 17 return vector<int>{x,y}; 18 } 19 };
2.剑指 Offer 56 - II. 数组中数字出现的次数 II
几点:1.各二进制位的位运算规则相同 ,因此只需考虑一位即可。拿一位去分析,但计算按整体计算(每一位都是一样的分析,那么 整体一起分析 和 逐个逐个的分析 结果也是一样的)
2.two的值!是求 one更新之后 的two的值!00 01 10
3.有限状态机的难点就在于求one和two时如何优化成一行代码
/*-----------------------------------------------------分割线----------------------------------------------------------------*/
依旧是k神的题解 https://leetcode.cn/leetbook/read/illustration-of-algorithm/9hctss/
但是!我不允许有人没看到这篇优秀的评论!救命SOS!优秀本秀








1 class Solution { 2 public: 3 int singleNumber(vector<int>& nums) { 4 int ones = 0, twos = 0; 5 for(int num : nums){ 6 ones = ones ^ num & ~twos; 7 twos = twos ^ num & ~ones; 8 } 9 return ones; 10 } 11 };

浙公网安备 33010602011771号