【Leetcode】338. Bit位计数

每次刷leetcode都有一种发现新大陆的感觉。

题目链接:https://leetcode-cn.com/problems/counting-bits/description/

给定一个非负整数 num。 对于范围 0 ≤ i ≤ num 中的每个数字 i ,计算其二进制数中的1的数目并将它们作为数组返回。

示例:
比如给定 num = 5 ,应该返回 [0,1,1,2,1,2].

进阶:

    • 给出时间复杂度为O(n * sizeof(integer)) 的解答非常容易。 但是你可以在线性时间O(n)内用一次遍历做到吗?
    • 要求算法的空间复杂度为O(n)。
    • 你能进一步完善解法吗? 在c ++或任何其他语言中不使用任何内置函数(如c++里的 __builtin_popcount)来执行此操作。

0    0000    0
-------------
1    0001    1
-------------
2    0010    1
3    0011    2
-------------
4    0100    1
5    0101    2
6    0110    2
7    0111    3
-------------
8    1000    1
9    1001    2
10   1010    2
11   1011    3
12   1100    2
13   1101    3
14   1110    3
15   1111    4

找规律,以分割线为界限。比如4-7。4,5和2,3相同,但是6,7却是2,3 加 1. 而8-15也符合类似的规则。可以用这个规律写下代码。

大神解法:

1 public int[] countBits(int num) {
2     int[] f = new int[num + 1];
3     for (int i=1; i<=num; i++)
4         f[i] = f[i >> 1] + (i & 1);
5     return f;
6 }

下面这种方法就更加巧妙了,巧妙的利用了i&(i - 1), 这个本来是用来判断一个数是否是2的指数的快捷方法,比如8,二进制位1000, 那么8&(8-1)为0,只要为0就是2的指数, 那么我们现在来看一下0到15的数字和其对应的i&(i - 1)值:

i    bin       ‘1‘    i&(i-1)
0    0000    0
-----------------------
1    0001    1    0000
-----------------------
2    0010    1    0000
3    0011    2    0010
-----------------------
4    0100    1    0000
5    0101    2    0100
6    0110    2    0100
7    0111    3    0110
-----------------------
8    1000    1    0000
9    1001    2    1000
10   1010    2    1000
11   1011    3    1010
12   1100    2    1000
13   1101    3    1100
14   1110    3    1100
15   1111    4    1110

我们可以发现每个i值都是i&(i-1)对应的值加1,这样我们就可以写出代码如下:

 1 class Solution {
 2 public:
 3     vector<int> countBits(int num) {
 4         vector<int> res(num + 1, 0);
 5         for (int i = 1; i <= num; ++i) {
 6             res[i] = res[i & (i - 1)] + 1;
 7         }
 8         return res;
 9     }
10 };

唉,都市人才啊。怎么想到的

原文地址:https://www.cnblogs.com/wenbochang/p/9032822.html

时间: 2024-10-06 05:36:51

【Leetcode】338. Bit位计数的相关文章

Leetcode——338. 比特位计数

题目描述:题目链接 对于求解一个十进制数转化为二进制时里面1的个数,可以先看一下概况: 十进制数 二进制数 1的个数 1 1    1 2 10 1 3 11   2 4 100 1 5 101 2 6 110   2 7 111   3 看上面的一系列数字的二进制中1的个数: 对于一个偶数 n :其二进制组成最低位为0,所以其1的位数就是除了最低位之外前面那一部分中1的位数,即是i/2中1的位数. 对于一个奇数n,其末位的数一定是1,那么对于n-1,一定是个偶数,并且只需要将n-1的末位0改成

338.比特位计数( Counting Bits)leetcode

附上:题目地址:https://leetcode-cn.com/problems/counting-bits/submissions/ 1:题目: 给定一个非负整数 num.对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回. 示例 1: 输入: 2 输出: [0,1,1]示例 2: 输入: 5 输出: [0,1,1,2,1,2]进阶: 给出时间复杂度为O(n*sizeof(integer))的解答非常容易.但你可以在线性时间O(n)内用一趟

【LeetCode】338. 比特位计数(位运算)

给定一个非负整数?num.对于?0 ≤ i ≤ num 范围中的每个数字?i?,计算其二进制数中的 1 的数目并将它们作为数组返回. 示例 1: 输入: 2 输出: [0,1,1] 示例?2: 输入: 5 输出: [0,1,1,2,1,2] 解法1:使用库函数 class Solution { public int[] countBits(int num) { int[] arr = new int[num + 1]; for(int i = 0; i <= num; i++){ arr[i]

338. 比特位计数

定一个非负整数 num.对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回. 示例 1: 输入: 2 输出: [0,1,1] 示例 2: 输入: 5 输出: [0,1,1,2,1,2] 进阶: 给出时间复杂度为O(n*sizeof(integer))的解答非常容易.但你可以在线性时间O(n)内用一趟扫描做到吗? 要求算法的空间复杂度为O(n). 你能进一步完善解法吗?要求在C++或任何其他语言中不使用任何内置函数(如 C++ 中的 __bui

java代码验证用户名,支持中英文(包括全角字符)、数字、下划线和减号 (全角及汉字算两位),长度为4-20位,中文按二位计数

package com.sangedabuliu.www; import java.util.regex.Matcher; import java.util.regex.Pattern; public class UserReg { /** * 验证用户名,支持中英文(包括全角字符).数字.下划线和减号 (全角及汉字算两位),长度为4-20位,中文按二位计数 * @author www.sangedabuliu.com * @param userName * @return */ public

[Leetcode] 第338题 比特位计数

一.题目描述 给定一个非负整数 num.对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回. 示例 1: 输入: 2 输出: [0,1,1] 示例 2: 输入: 5 输出: [0,1,1,2,1,2] 二.题目分析 1)发现规律:2的幂1的数目一定是1个,用last_2记录最近出现的2的幂2)dp[i]=1+dp[i-last_2],比如dp[7]=1+dp[3] 三.代码实现 1 class Solution { 2 public: 3 v

338. Counting Bits_比特位计数_简单动态规划

https://leetcode.com/problems/counting-bits/ 这是初步了解动态规划后做的第一道题,体验还不错... 看完题目要求后,写出前10个数的二进制数,发现了以下规律: 2的幂的二进制数中只有一个1 若n不是2的幂,可以拆分为两个数的和(a+b),a为比n小的最接近的2的幂 拆分后,res[n] = res[a] + res[b] class Solution { public: vector<int> countBits(int num) { int bas

leetcode 75 Sort Colors 计数排序,三路快排

解法一:计数排序:统计0,1,2 的个数 时间复杂度:O(n) 空间复杂度:O(k)    k为元素的取值范围, 此题为O(1) class Solution { public: void sortColors(vector<int>& nums) { int count[3] = {0}; //存放0,1,2三个元素的频率 for(int i=0;i<nums.size();i++){ assert(nums[i] >=0 && nums[i]<=2

【Leetcode 338】 Counting Bits

---恢复内容开始--- 问题描述:给出一个非负整数num,对[0, num]范围内每个数都计算它的二进制表示中1的个数 Example:For num = 5 you should return [0,1,1,2,1,2] 思路:这种题适合归纳法,找出规律然后用编程语言描述,令i从0开始,设f(i)为i对应二进制表示中1的个数 也就是每次有一个大小为2^n的序列,把他们每个数都加1,然后插入到结尾就构成了大小为2^(n+1)个序列. 直到2^(n+1)比num大,取前num个数组成序列返回即可