第一题 力扣
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
class Solution {
public:
int singleNumber(vector<int>& nums) {
unordered_map<int, int> hashtable;
for (int i = 0; i < nums.size();i++) {
auto it = hashtable.find(nums[i]);
if (it != hashtable.end()) {
hashtable.erase(it);
}
else{
hashtable[nums[i]] = i;
}
}
return hashtable.begin()->first;
}
};
第一时间想到的就是用hashtable,用stl的内置函数解决。
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ans =0;
for (int i = 0; i < nums.size();i++) {
ans^=nums[i];
}
return ans;
}
};
也可以遍历一次,使用位运算中的异或操作的性质找出只出现一次的数。
第二题 力扣
给你一个整数数组
nums
。数组中唯一元素是那些只出现 恰好一次 的元素。请你返回
nums
中唯一元素的 和 。
class Solution {
public:
int sumOfUnique(vector<int>& nums) {
int hash[101];
int sum=0;
memset(hash,0,sizeof(hash));
for(int i=0;i<nums.size();++i){
++hash[nums[i]];
}
for(int i=0;i<nums.size();++i){
if(hash[nums[i]]==1){
sum+=nums[i];
}
}
return sum;
}
};
与第一题类似,用hash表示每个数字的出现次数,最后简单加和即可。
class Solution {
public:
int sumOfUnique(vector<int>& nums) {
int ans =0;
unordered_map<int,int>state;
for(int num:nums){
if(state[num]==0){
ans+=num;
state[num]=1;
}
else if(state[num]==1){
ans-=num;
state[num]=2;
}
}
return ans;
}
};
题解里面的方法比较有意思,类似于一种状态机的方法,第一次遍历先全部加进去再设置状态, 如果遍历到已经有了的再减掉。
第三题 力扣
给定一个包含
[0, n]
中n
个数的数组nums
,找出[0, n]
这个范围内没有出现在数组中的那个数。
class Solution {
public:
int missingNumber(vector<int>& nums) {
int n=nums.size();
int sum= (0+n)*(1+n)/2;
for(int i=0;i<n;++i){
sum-=nums[i];
}
return sum;
}
};
总数里减去出现的就是未出现的数。
第四题 力扣
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
class Solution {
public:
int missingNumber(vector<int>& nums) {
int n = nums.size();
int sum = (n+1)*n/2;
for(int i=0;i<nums.size();++i){
sum-=nums[i];
}
return sum;
}
};
与上面一题思路基本一致。
第五题 力扣
给你两个整数,n 和 start 。
数组 nums 定义为:nums[i] = start + 2*i(下标从 0 开始)且 n == nums.length 。
请返回 nums 中所有元素按位异或(XOR)后得到的结果。
class Solution {
public:
int xorOperation(int n, int start) {
int ans =0;
for(int i=0;i<n;++i){
ans^=start + 2*i;
}
return ans;
}
};
简单遍历数组元素即可。
第六题 力扣
每个非负整数 N 都有其二进制表示。例如, 5 可以被表示为二进制 "101",11 可以用二进制 "1011" 表示,依此类推。注意,除 N = 0 外,任何二进制表示中都不含前导零。
二进制的反码表示是将每个 1 改为 0 且每个 0 变为 1。例如,二进制数 "101" 的二进制反码为 "010"。
给你一个十进制数 N,请你返回其二进制表示的反码所对应的十进制整数。
class Solution {
public:
int bitwiseComplement(int n) {
int k =0;
if(n==0){
return 1;
}
while(1){
if((1<<k)>n){
break;
}
++k;
}
return (1<<k)-1-n;
}
};
一个数10101与其反码01010之和为2^k-1,k为二进制的位数。
所以我们先用一个循环找出这个数二进制的位数,再算出2^k-1(即(1<<k)-1),减去n即可。
第七题 力扣
对整数的二进制表示取反(0 变 1 ,1 变 0)后,再转换为十进制表示,可以得到这个整数的补数。
例如,整数 5 的二进制表示是 "101" ,取反后得到 "010" ,再转回十进制表示得到补数 2 。
给你一个整数 num ,输出它的补数。
class Solution {
public:
int findComplement(int num) {
int k= 0;
if(num==0){
return 1;
}
while(1){
if(((long long)1<<k)>num){
break;
}
++k;
}
return ((long long)1<<k)-1-num;
}
};
与上一题基本相同,但是<<过程中可能会溢出,所以强制转换成long long格式即可。
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为 汉明重量).)
class Solution {
public:
int hammingWeight(uint32_t n) {
int sum=0;
while(n){
if(1&n){
++sum;
}
n>>=1;
}
return sum;
}
};
循环,利用1&n比较最后一位是否为1;
然后右移比较下一位,以此类推。
第九题 力扣
两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。
class Solution {
public:
int hammingDistance(int x, int y) {
int s=x^y;
int sum=0;
while(s){
if(1&s){
++sum;
}
s>>=1;
}
return sum;
}
};
不同的位数我们可以先用异或操作标识出来,再用循环以及同或操作数出不同的位数。
第十题 力扣
一次 位翻转 定义为将数字 x 二进制中的一个位进行 翻转 操作,即将 0 变成 1 ,或者将 1 变成 0 。
比方说,x = 7 ,二进制表示为 111 ,我们可以选择任意一个位(包含没有显示的前导 0 )并进行翻转。比方说我们可以翻转最右边一位得到 110 ,或者翻转右边起第二位得到 101 ,或者翻转右边起第五位(这一位是前导 0 )得到 10111 等等。
给你两个整数 start 和 goal ,请你返回将 start 转变成 goal 的 最少位翻转 次数。
class Solution {
public:
int minBitFlips(int start, int goal) {
int s =start^goal;
int sum=0;
while(s){
if(1&s){
++sum;
}
s>>=1;
}
return sum;
}
};
这个题目中所说的最小位翻转次数就是两个数之间的“汉明距离”。