1059-前 n 个数字二进制中 1 的个数

2023-10-26

题目如下

给定一个非负整数 n ,请计算 0 到 n 之间的每个数字的二进制表示中 1 的个数,并输出一个数组。

示例 1:
输入: n = 2
输出: [0,1,1]
解释:
0 --> 0
1 --> 1
2 --> 10

示例 2:
输入: n = 5
输出: [0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101

这道题需要计算从 0 到 n 的每个整数的二进制表示中的 1 的数目。

部分编程语言有相应的内置函数用于计算给定的整数的二进制表示中的 1 的数目,例如 Java 的Integer.bitCount,C++ 的 __builtin_popcount,Go 的 bits.OnesCount 等,读者可以自行尝试。下列各种方法均为不使用内置函数的解法。

为了表述简洁,下文用「一比特数」表示二进制表示中的 1 的数目。

解题思路1

方法一:Brian Kernighan 算法
最直观的做法是对从 0 到 n 的每个整数直接计算「一比特数」。每个 int 型的数都可以用 32 位二进制数表示,只要遍历其二进制表示的每一位即可得到 1 的数目。

利用 Brian Kernighan 算法,可以在一定程度上进一步提升计算速度。Brian Kernighan 算法的原理是:对于任意整数 x,令x=x & (x−1),该运算将 x 的二进制表示的最后一个 1 变成 0。因此,对 x 重复该操作,直到 x 变成 0,则操作次数即为 x 的「一比特数」。

对于给定的 n,计算从 0 到 n 的每个整数的「一比特数」的时间都不会超过 O(logn),因此总时间复杂度为 O(nlogn)。

class Solution 
{
public:
    int countOnes(int x) 
    {
        int ones = 0;
        while (x > 0) 
        {
            x &= (x - 1);
            ones++;
        }
        return ones;
    }

    vector<int> countBits(int n) 
    {
        vector<int> bits(n + 1);
        for (int i = 0; i <= n; i++) 
        {
            bits[i] = countOnes(i);
        }
        return bits;
    }
};

复杂度分析

时间复杂度:O(nlogn)。需要对从 0 到 n 的每个整数使用计算「一比特数」,对于每个整数计算「一比特数」的时间都不会超过 O(logn)。

空间复杂度:O(1)。除了返回的数组以外,空间复杂度为常数。

方法二:动态规划——最高有效位

在这里插入图片描述
最终得到的数组 \textit{bits}bits 即为答案。

class Solution
{
public:
    vector<int> countBits(int n) 
    {
        vector<int> bits(n + 1);
        int highBit = 0;
        for (int i = 1; i <= n; i++) 
        {
            if ((i & (i - 1)) == 0) 
            {
                highBit = i;
            }
            bits[i] = bits[i - highBit] + 1;
        }
        return bits;
    }
};

复杂度分析

时间复杂度:O(n)。对于每个整数,只需要 O(1) 的时间计算「一比特数」。

空间复杂度:O(1)。除了返回的数组以外,空间复杂度为常数。

方法三:动态规划——最低有效位

在这里插入图片描述

class Solution 
{
public:
    vector<int> countBits(int n) 
    {
        vector<int> bits(n + 1);
        for (int i = 1; i <= n; i++) 
        {
            bits[i] = bits[i >> 1] + (i & 1);
        }
        return bits;
    }
};

复杂度分析

时间复杂度:O(n)。对于每个整数,只需要 O(1) 的时间计算「一比特数」。

空间复杂度:O(1)。除了返回的数组以外,空间复杂度为常数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

1059-前 n 个数字二进制中 1 的个数 的相关文章

随机推荐

  • 这个高仿小米商城项目太惊艳了

    我的引语 晚上好 我是吴小龙同学 我的公众号 菜鸟翻身 会推荐 GitHub 上好玩的项目 一分钟 get 一个优秀的开源项目 挖掘开源的价值 欢迎关注我 平时总觉得还有很多事情要去做 然而当真的闲下来时却不一定去做 比如今年这个天天在家窝
  • LPMM阅读笔记

    https www cnblogs com ChipView p 9278614 html LPMM阅读笔记 第1章 引言 LPMM阅读笔记 1 写给自己 转眼间我已经工作了两年 在这两年里 为了工作需要我看了很多相关书籍 在我看书的时候都
  • Linux·软中断&tasklet

    目录 软中断 中断服务接口管理 tasklet 软中断 首先明确一个概念软中断 不是软件中断int n 总来来说软中断就是内核在启动时为每一个内核创建了一个特殊的进程 这个进程会不停的poll检查是否有软中断需要执行 如果需要执行则调用注册
  • 网络爬虫js逆向解决网站登录RSA加密问题,不使用selenium如何实现登录,session维持登录状态请求爬取

    记录中大网校破解登录后爬取的方法 案例请求地址 中大网校会员中心 登陆入口 中大网校 使用工具 打码平台 超级鹰 分析请求 分析此请求 得知没有data 保持状态登录需要服务器知道是这个用户对应请求的相应验证码 所以要用session来维护
  • Spring Boot中自定义注解

    在Spring Boot中 我们可以通过自定义注解来实现一些特定的功能 自定义注解可以让我们的代码更加简洁 易于维护 并且可以提高代码的可读性和可扩展性 本文将介绍如何在Spring Boot中自定义注解 定义注解 首先 我们需要定义一个注
  • Qt读写CSV文件的几种方式及优劣

    前言 作为一种常见的数据交换格式 CSV Comma Separated Values 文件常常用于数据导出和导入等场合 在实际开发中 我们也需要使用Qt来实现CSV文件的读写操作 本篇博客将介绍使用Qt实现CSV读写的方法 并分析每种实现
  • ttlink无线打印服务器固件,TTLINK TT-180U1打印机服务器 TCP/IP添加打印机的教程

    使用TT 180U1 LPR添加方式 本教程以打印机为兄弟HL 2140激光打印机为实例 系统为Windows 7 64位系统 打印服务器IP固定为192 168 1 220 优点 不用安装软件 打印速度快 稳定性好 可跨网段打印 缺点 只
  • Python

    实现思路 分为两部分 第一部分 获取网页上数据并使用xlwt生成excel 当然你也可以选择保存到数据库 第二部分获取网页数据使用IO流将图片保存到本地 一 爬取所有英雄属性并生成excel 1 代码 import json import
  • Windows系统安装及初步使用ImageMagick

    最近在网上搜索了很多关于 Windows系统安装及如何使用ImageMagick 的相关文章 都没有详细说明如何使用 经过自己的摸索才明白如何使用 所以今天把它记录下来 1 首先第一步肯定是去官网下载安装包 http www imagema
  • Zotero(2)---使用Sci-hub插件下载文献

    Sci hub插件配置 如果没有安装zotero可以参考https blog csdn net u011895157 article details 126144104 spm 1001 2014 3001 5501 1 首先打开zoter
  • HTML常用的标签

    目录 1 段落 行内 换行标签 2 文本样式标签 3 表格标签 4 表单标签 1 表单域 2 表单控件 5 列表标签 6 超链接标签 7 图像标签 1 段落 行内 换行标签 为了让网页的文字有条理的显示出来 HTML有 p 段落标签 和 s
  • excel中如何将3'30"格式的分秒转换成以秒为单位的数字?

    在excel中 如记录比赛成绩的格式为3 30 要转换成以秒为单位的数字 如210秒的方式 请问该如何操作 假设你的数据在A列 A1 A100 在B1输入下面的公式 然后向下填充 TEXT 00 SUBSTITUTE LEFT A1 LEN
  • C# SuperSocket利用FixedHeaderReceiveFilter或BeginEndMarkReceiveFilter进行通信

    SuperSocket 是一个轻量级 跨平台而且可扩展的 Net Mono Socket 服务器程序框架 你无须了解如何使用 Socket 如何维护 Socket 连接和 Socket 如何工作 我们可以有更多的时间用在业务逻辑上 Supe
  • 大一python作业

    1 字典操作综合练习一 定义一个字典 goods Apple 4999 华为 3600 Vivo 2999 OPPO 3200 三星 4300 向字典新增一个 小米 手机 价格为2800 将字典中 华为 品牌手机价格修改为3999 输入任一
  • 淘宝的双11、春运时的抢票、微博大V的热点新闻,Alibaba双11的高并发实战经验,被这份文档诠释的极透彻

    前言 高并发意味着大流量 需要运用技术手段抵抗流量的冲击 这些手段好比操作流量 能让流量更平稳地被系统所处理 带给用户更好的体验 我们常见的高并发场景有 淘宝的双11 春运时的抢票 微博大V的热点新闻等 除了这些典型事情 每秒几十万请求的秒
  • React中的路由懒加载是什么?原理是什么?

    React lazy 是什么 随着前端应用体积的扩大 资源加载的优化是我们必须要面对的问题 动态代码加载就是其中的一个方案 webpack 提供了符合 ECMAScript 提案 的 import 语法 让我们来实现动态地加载模块 注 re
  • C++模板 类模板成员函数类外实现 类模板分文件编写的问题与解决方法 类模板配合友元函数的类内和类外实现

    文章目录 1 类模板成员函数类外实现 2 类模板分文件编写 3 类模板友元 1 类模板成员函数类外实现 学习目标 能够掌握类模板中的成员函数类外实现 场景描述 创建一个类 类中只写函数的声明 类外写实现 template
  • Git第五讲 git pull/git fetch与 git rebase/git merge

    当你和其他开发者一起协作开发项目时 经常会遇到需要更新代码的情况 Git提供了多种方式来获取最新代码并将其合并到你的本地仓库中 在本篇博客中 我们将详细介绍git pull和git fetch命令的使用 以及git rebase和git m
  • 【目标检测】Faster R-CNN的复现

    文章目录 Faster Rcnn 0 利用Git下载Code 1 数据准备 2 模型加载 3 模型训练 4 模型测试 5 运行demo py 6 训练自定义Images文件和对应XML文件的model Faster Rcnn Faster
  • 1059-前 n 个数字二进制中 1 的个数

    题目如下 给定一个非负整数 n 请计算 0 到 n 之间的每个数字的二进制表示中 1 的个数 并输出一个数组 示例 1 输入 n 2 输出 0 1 1 解释 0 gt 0 1 gt 1 2 gt 10 示例 2 输入 n 5 输出 0 1