Leetcode 每日一题和每日一题的下一题刷题笔记 23/30
写在前面
这是我参与更文挑战的第23天,活动详情查看:更文挑战
快要毕业了,才发现自己被面试里的算法题吊起来锤。没办法只能以零基础的身份和同窗们共同加入了力扣刷题大军。我的同学们都非常厉害,他们平时只是谦虚,口头上说着自己不会,而我是真的不会。。。乘掘金鼓励新人每天写博客,我也凑个热闹,记录一下每天刷的前两道题,这两道题我精做。我打算每天刷五道题,其他的题目嘛,也只能强行背套路了,就不发在博客里了。
本人真的只是一个菜鸡,解题思路什么的就不要从我这里参考了,编码习惯也需要改进,各位如果想找刷题高手请教问题我觉得去找 宫水三叶的刷题日记 这位大佬比较好。我在把题目做出来之前尽量不去看题解,以免和大佬的内容撞车。
另外我也希望有得闲的大佬提供一些更高明的解题思路给我,欢迎讨论哈!
好了废话不多说开始第二十三天的前两道题吧!
2021.6.23 每日一题
这道题是简单题,但是玩法很多,面试的时候可以根据题目要求给出各种各样的优化,这次的参考链接里面给出了很多有意思的解法,各位可以去看看。
我用这个相邻位相加的做法来把最后 1 的个数数出来。
class Solution {
public:
int hammingWeight(uint32_t n) {
n = (n & 0x55555555) + ((n >> 1) & 0x55555555);
n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
n = (n & 0x0f0f0f0f) + ((n >> 4) & 0x0f0f0f0f);
n = (n & 0x00ff00ff) + ((n >> 8) & 0x00ff00ff);
n = (n & 0x0000ffff) + ((n >> 16) & 0x0000ffff);
return n ;
}
};
这个解释起来也很简单,把这些十六进制的数展开,可以看到一层一层的满二叉树,1 的个数就这么层层相加最后在根节点上得到全部 1 的个数。
0101 0101 0101 0101 0101 0101 0101 0101 (0x55555555)
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ (n)
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ (n >> 1)
0^0^ 0^0^ 0^0^ 0^0^ 0^0^ 0^0^ 0^0^ 0^0^ (result)
0011 0011 0011 0011 0011 0011 0011 0011 (0x33333333)
^ ^ ^ ^ ^ ^ ^ ^ (n)
^ ^ ^ ^ ^ ^ ^ ^ (n >> 2)
000^ 000^ 000^ 000^ 000^ 000^ 000^ 000^ (result)
0000 1111 0000 1111 0000 1111 0000 1111 (0x0f0f0f0f)
^ ^ ^ ^ (n)
^ ^ ^ ^ (n >> 4)
0000 000^ 0000 000^ 0000 000^ 0000 000^ (result)
0000 0000 1111 1111 0000 0000 1111 1111 (0x00ff00ff)
^ ^ (n)
^ ^ (n >> 8)
0000 0000 0000 000^ 0000 0000 0000 000^ (result)
0000 0000 0000 0000 1111 1111 1111 1111 (0x0000ffff)
^ (n)
^ (n >> 16)
0000 0000 0000 0000 0000 0000 0000 000^ (result)
2021.6.23 每日一题下面的题
剑指 Offer 56 - II. 数组中数字出现的次数 II
依然可以上位运算,这次这么来
class Solution {
public:
int singleNumber(vector<int>& nums) {
int res = 0;
for (int i = 0, sub = 0; i < 32; ++i, sub = 0) {
for (auto &n : nums) sub += ((n >> i) & 1);
if (sub % 3) res |= (1 << i);
}
return res;
}
};
举个例子吧,依然用32位来表示一个数,用 nums = [9,1,7,9,7,9,7] 这个例子。
0000 0000 0000 0000 0000 0000 0000 1001 (9)
0000 0000 0000 0000 0000 0000 0000 0001 (1)
0000 0000 0000 0000 0000 0000 0000 0111 (7)
0000 0000 0000 0000 0000 0000 0000 1001 (9)
0000 0000 0000 0000 0000 0000 0000 0111 (7)
0000 0000 0000 0000 0000 0000 0000 1001 (9)
0000 0000 0000 0000 0000 0000 0000 0111 (7)
0000 0000 0000 0000 0000 0000 0000 3337 (每个二进制位上,出现 `1` 的次数)
0000 0000 0000 0000 0000 0000 0000 0001 (每个二进制位上,出现 `1` 的次数对 3 求余数,正好也是那个不重复的数)
小结
位运算是个好玩的东西,只要手边有二进制计算器或者有张纸,随便画画说不定能开拓思路。位运算只是方法比较巧妙,但是效率真不一定是最好的,这还是要看具体题目和具体算法。