查找输入整数二进制中1的个数
思路:
本题是计算一个数二进制表示中1的个数,通过(n >> i) & 1可以获取第i位的二进制值,每次n右移一位,可以获取一位的二进制值,右移32次,n变成0,循环终止。
代码:
#include<iostream>
using namespace std;
int main() {
int num = 0;
while (cin >> num) {
int sum = 0;
while (num) {
if ((num & 1) == 1) {
sum++;
}
num = num >> 1;
}
cout << sum << endl;
}
return 0;
}
手套问题
思路:
本题的意思是随意取出的手套至少可以形成一组组合的最少手套数量。题目给的两个数组对应位置表示同一种颜色的左右手套数量。
对于非0递增序列a1,a2...an
,要想最终取值覆盖每一个种类,那么 n = sum(a1…an) - a1 + 1(总数-最小值+1
) ,所以对于左右手手套颜色都有数量的序列,想要覆盖每一种颜色,则最小数量leftsum = 左边数量和 - 左边最小值 + 1
, rightsum = 右边数量和 - 右边的最小值 + 1
。
设总共需要拿SUM个手套才能凑出一对;
总的来说就是左(右)边任意一个所有颜色都覆盖,然后再随便在右(左)边再随便拿一个,即可选出一双颜色相同的左右手手套。
而对于某一边某种颜色数量是0,则需要直接将另一边对应颜色的手套数加到SUM中,才能保证覆盖每一种颜色(从最坏的情况来考虑),这个仔细想一下其实就可以明白。
最终表达式:SUM=sum + min(left_sum - left_min + 1, right_sum - right_min + 1) + 1
sum
代表左手或者右手有0存在的手套数,这样的特殊情况无论如何都是凑不齐一对手套的,所以要直接算入SUM中。(最坏情况)
min(left_sum - left_min + 1, right_sum - right_min + 1)
代表左手或者右手颜色不为0的小的那一边的手套数,取数量小的那一边,我们达到所有颜色都覆盖的目的即可,要整体考虑。
最后再加一
即可选出一双颜色相同的左右手手套,满足题意。
代码:
class Gloves {
public:
int findMinimum(int n, vector<int> left, vector<int> right) {
int left_sum = 0, left_min = INT_MAX;
int right_sum = 0, right_min = INT_MAX;
int sum = 0;
//遍历每一种颜色的左右手套序列
for (int i = 0; i < n; i++) {
//对于有0存在的颜色手套,累加
if (left[i]*right[i] == 0)
sum += left[i] + right[i];
//对于左右手都有的颜色手套,累加
//找到最小值 和 总数
else {
left_sum += left[i];
right_sum += right[i];
left_min = min(left_min, left[i]);
right_min = min(right_min, right[i]);
}
}
//结果为 有0存在的手套数+左右都有数量的手套+最后再加一
return sum + min(left_sum - left_min + 1, right_sum - right_min + 1) + 1;
}
};
end