

算法简单题,吾辈重拳出击 - 前 n 个数字二进制中 1 的个数
source link: https://blog.51cto.com/u_13961087/5610753
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

算法简单题,吾辈重拳出击 - 前 n 个数字二进制中 1 的个数
推荐 原创最近做的题,明眼人一看都能知道大都和动态规划 DP 有关,因为就是从动态规划分类下抽取的简单题,有的题在剑指 offer 系列中是简单题,但是在力扣主列表里确实中等难度的题目。
简单与难,也并非是绝对的,每个人的感受都会不同。更重要的是,通过这些题构建基础的算法思路,建立信心。
动态规划在查找有很多重叠子问题的情况的最优解时有效。它将问题重新组合成子问题。为了避免多次解决这些子问题,它们的结果都逐渐被计算并被保存,从简单的问题直到整个问题都被解决。因此,动态规划保存 递归时的结果,因而不会在解决同样的问题时花费时间。
动态规划 => 子问题 => 复用计算结果(通常伴随比较得值) => 递归(通常一遍循环即可)

OK,简单温故思路,再开始本篇题目:前 n 个数字二进制中 1 的个数
给定一个非负整数
n
,请计算 0
到 n
之间的每个数字的二进制表示中 1 的个数,并输出一个数组。
输出: [0,1,1]
解释:
0 --> 0
1 --> 1
2 --> 10
输出: [0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101
n=2,就要写出 0、1、2 的二进制,分别是 0 、1、10,分别有1的个数:0、1、1
n=3,就要写出 0、1、2、3 的二进制,分别是0、1、10、11,分别有1的个数:0、1、1、2
同理 n=4 => [0,1,1,2,1]
n=5 => [0,1,1,2,1,2]
......
设结果数组 res = []
暴力解法,算出每一个数字的二进制有几个1,然后 push 进数组;
怎么算出二进制有几个 1 ?
部分编程语言有相应的内置函数用于计算给定的整数的二进制表示中的 11 的数目,例如 Java 的 Integer.bitCount、C++ 的 _ _builtin_popcount、Go 的 bits.OnesCount 等;
在 javascript 没有这个方法,所以需要我们自己写一个。
这里需要用到与操作 —— “&”
x = x & (x-1) 用于去除整数 x 二进制最右边的 1,递进移除,进行计数。
每次移除最右侧的 1 ,计数加一,直到全部做与操作,归为为0,输出统计次数;
举个例子,比如 x = 5 :
x = 5 & 4;
// 5: 00000000000000000000000000000101
// 4: 00000000000000000000000000000100
第1次与结果 x:
// 00000000000000000000000000000100
x = x & 3
// x: 00000000000000000000000000000100
// 3: 00000000000000000000000000000011
第2次与结果 x:
// 00000000000000000000000000000000
结果 = 0,结束,共计 2 次与操作,即 5 的二进制有 2 个 1;
算法表示为:
let count = 0;
while(x > 0){
x &= x - 1;
// 统计次数
count++;
}
return count;
}
有了上一步的判断,拿到结果输入,轻而易举。
let res = []
let countOnes = function(x){
let count = 0;
while(x > 0){
x &= x - 1;
// 统计次数
count++;
}
return count;
}
for(let i = 0;i<=n;i++){
res.push(countOnes(i))
}
return res
};

上述算法需要对每个数都做 countOnes 操作,countOnes 操作里面又有一个循环,整个时间复杂度肯定是大于 O(n) 的;
还能不能再优化优化?动态规划 DP 来帮忙!
DP 就是将大问题抽象为一个小的具体问题,用公式表达。 通常由后向前导,遍历一次,时间复杂度更小。
看看官方解答思路:
此题中,对于正整数 x,如果可以知道最大的正整数 y,y≤x 且 y 是 2 的整数次幂,y 的二进制表示中只有最高位是 1,其余都是 0,此时称 y 为 x 「最高有效位」
则:bits[x] = bits [x - y] + 1
怎么理解?(OS: 不好理解。。。就先记住这个规则吧,欢迎大神解释QAQ)
bits[5] = bits [5 - 4] + 1 = bits[1] + 1 = 2
// 比如正整数 8,小于等于 7 的最大正整数,且它是 2 的整数次幂,且只有最高位是 1,其余都为 0 的是数字 4
bits[7] = bits [7 - 4] + 1 = bits[3] + 1 = 3
// 比如正整数 8,小于等于 8 的最大正整数,且它是 2 的整数次幂,且只有最高位是 1,其余都为 0 的是数字 8
bits[8] = bits [8 - 8] + 1 = bits[0] + 1 = 1
对照下面整个表可以试试,bits[x] = bits [x - y] + 1
这条抽象规则是对的。

那怎样知道这个 y 等于几?
y 的二进制表示中只有最高位是 1,其余都是 0,因此 y & (y−1)=0
for 循环一层 x,当 x & (x−1)=0 的时候,更新 y 值,循环完毕,y 值肯定是最大的那个。
最终实现:
let bits = new Array(n + 1).fill(0) // 结果数组要多一位
let y = 0
for(let i = 1; i <= n; i++) {
if ((i & (i - 1)) == 0) {
y = i;
}
bits[i] = bits[i - y] + 1;
}
return bits
}
动态规划的另外一种解释!通透!!!❤
根据 i & (i-1) 计算i的二进制形式中1的个数
i & (i-1) 能将整数i的二进制形式最右边的1变为0
那么 整数i的二进制中1的个数比整数i&(i-1)的二进制中1的个数多1
let res = new Array(n + 1).fill(0);
for (let i = 1; i <= n; i++) {
res[i] = res[i & (i - 1)] + 1;
}
return res;
};
小结:
本题说简单,其实也并不简单~
与 & 操作得二进制 1 的个数在实际工作中并不多见,本瓜觉得这里更重要的是再次过一遍动态规划的简单题基础思维:
动态规划 => 子问题 => 复用计算结果(通常伴随比较得值、更新值) => 递归(通常一遍循环即可)
OK,以上便是本篇分享。点赞关注评论,为好文助力👍
我是掘金安东尼 🤠 100 万人气前端技术博主 💥 INFP 写作人格坚持 1000 日更文 ✍ 关注我,安东尼陪你一起度过漫长编程岁月 🌏
Recommend
-
11
APP侵权屡禁不止?工信部再次重拳出击_大数据资讯_中国IDC圈 APP侵权屡禁不止?工信部再次重拳出击 在当下这个互联网发达的时代,各式各样的APP层数不穷,在给人们提供便利的同时也开始给人们的生活带来一定的风险。
-
8
2021-05-22 12:58 监管再次重拳出击,后市如何? 昨天一条重要的消息在圈内刷屏:在国务院副总理、金融委主任刘鹤主持召开的国务院金融稳定发展委员会第五十一次会议上,明确提出要坚决防控金融风险,强化平台企业金融活动监...
-
7
查看: 3219|回复: 14 [经济发展] 桥西区重拳出击拆除私搭私建
-
4
重拳出击!Gozilla、Motley Crue在八月立案4次,Snoopy、fox、Nirvana再次维权-跨境头条-AMZ123亚马逊导航-跨境电商出海门户 重拳出击!Gozilla、Motley...
-
5
欧盟要对苹果重拳出击,iPhone上的这个黑点以后要没了? iPhone 13 / 欧盟 时间:
-
5
Keep×拳皇'97:重拳出击,K.O.所有不服 ...
-
8
近期,抖音发布了《抖音电商平台治理这一年》数据报告,全面盘点了抖音平台的治理和成果。从今年4月初的抖音生态大会上,就可以看出抖音对平台生态建设的决心,提出想要有质量的GMV,用健康的平台生态实现长效经营。对于中小商家而言,这就意味着...
-
9
算法简单题,吾辈重拳出击 - 动态规划之爬楼梯 推荐 原创 DP 动态规划接着冲!经典之爬楼梯题目~
-
8
苹果走到交叉口!欧盟重拳出击 “苹果税”或将成历史? 评论(9)
-
7
海关总署重拳出击 跨境电商4项国标发布 “四海商舟”宣布倒闭清算 TikTok Shop发布年末大促季战报 | 跨境电商这一周 ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK