作品集怎么做网页丽水网站seo
只出现一次的数字
这道题目是要找出只出现一次的数字,其他数字都会出现两次
C语言可以直接用的位运算有按位与(&),按位或(|),按位异或(^)
这道题用到的是按位异或
先讲一下按位异或:
对于两个二进制数,相同为0,不同为1,上图中前两位是不同的,所以只有前两位为1,后三位都为1,所以这两个数按位异或的结果就是00011,即3
那两个相同的数按位异或的结果就是0
而0和任何数异或都会是另一个数
我们可以利用这个特性,来把所有的数都异或一遍,最后的结果就是单独的那个数了(相同的都变成0了,0和任何数异或都会是另一个数)
本题代码:
class Solution {
public:int singleNumber(vector<int>& nums) {int num = 0;for(auto e : nums){num^=e;}return num;}
};
只出现一次的数字II
本题和上题的唯一区别就是从出现两次变成了三次,那肯定不能再用按位异或了,这样异或出来的结果完全没有任何意义
但这一题还是考的位运算操作
先来讲讲按位与和按位或
按位与是双方位都为1才是1,按位或只需要双方有1个为1就是1
思路:
因为除了那一个数,其他数都出现三次,可以先用按位与来遍历每一个数,用一个[32]的数组把每一个位中的1都统计起来,只要有一位的1的个数不是3的倍数,那多出来的1就是多余的那个数的
具体实现:
class Solution {
public:int singleNumber(vector<int>& nums) {int er[32]={0};for(auto e : nums){for(int i=0;i<32;i++){if(e&(1<<i))//如果第i位是1{er[i]++;//那么第i位++}}}int p=0;for(int i = 0;i<32;i++){if(er[i]%3 != 0)//如果这一位1的个数不是3的倍数,那多出来的那个1就是属于只出现一次的数的{p |= (1<<i);//将p的第i位置成1}}return p;}
};
只出现一次的数字III
该题和第一题的区别是只出现一次的数字从1个变成了2个,那有没有什么办法可以将它转换成2个第一题呢?
可以确定的是,这两个只出现一次的数不是一样的,如果将这全部的数都异或,最后是两个只出现一次的数异或的结果,我们就可以通过这个结果来给它分组
具体实现:
class Solution {
public:vector<int> singleNumber(vector<int>& nums) {int num=0;for(auto e : nums)//将所有数都异或一遍,得到的结果就是只出现一次的那两个数异或的结果{num^=e;}int i;for(i=0;i<32;i++)//判断这个结果的哪一位是1,只要是1就代表这两个数的这一位不同{if(num & (1 << i))//不同就跳出break;}int num1=0,num2=0;for(auto e : nums)//然后根据这个不同的位来对这些数据分组,这样这两个只出现一次的数就被分到两组了{if(e & (1 << i))num1 ^= e;//就化解成了问题1了elsenum2 ^= e;}vector<int> v;v.push_back(num1);v.push_back(num2);return v;}
};