剑指offer 专项突破版 3、前 n 个数字二进制中 1 的个数

题目链接

思路

  • 思路一
    最简单的思路就是每一个数字单独算二进制下1的个数
    注意有一种简便算法就是利用 i & i-1 来让i最右侧的1变为0 所以说 i & i-1比i的二进制1的位数少1 利用这个规律可以快速的算出n在二进制下1的个数

    public class Solution {
        public int[] countBits(int n) {
            int[] result = new int[n + 1];
    
            for (int i = 0; i <= n; i++) {
                int count = 0, j = i;
    
                while (0 != j) {
                    result[i] += 1;
                    j &= j - 1;
                }
            }
            return result;
        }
    }
    

    这种解法注意

    1. 要引入变量j 而不能更新i
    2. while循环的判断条件是 0 != j
  • 思路二
    既然i & i-1比i的二进制1的位数少1 而我们的result数组保存的就是二进制形式1的位数 那么自然有result[i] = result[i&i-1]+1

    public class Solution {
        public int[] countBits(int n) {
            int[] result = new int[n + 1];
    
            for (int i = 0; i <= n; i++) {
                result[i] = result[i & i - 1] + 1;
            }
            return result;
        }
    }
    
  • 思路三
    思路三主要是对于规律的寻找 我们知道在二进制情况下 左移1位等价于乘2,所以对于i,必有result[2*i] = result[i]
    那么对于result[2 * i+1],则可以看成result[i]先左移1位再+1,因为此时刚左移结束,最低为一定是0,所以不会产生进位,所以result[2 * i+1] = result[2 * i]+1

    public class Solution {
        public int[] countBits(int n) {
            int[] result = new int[n + 1];
    
            for (int i = 1; i <= n; i++) {
                result[i] = result[i >> 1] + (1 & i);
            }
            return result;
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值