【1017. 负二进制转换】
来源:力扣(LeetCode)
描述:
给你一个整数 n ,以二进制字符串的形式返回该整数的 负二进制(base -2)表示。
注意, 除非字符串就是 "0",否则返回的字符串中不能含有前导零。
示例 1:
输入:n = 2
输出:"110"
解释:(-2)2 + (-2)1 = 2
示例 2:
输入:n = 3
输出:"111"
解释:(-2)2 + (-2)1 + (-2)0 = 3
示例 3:
输入:n = 4
输出:"100"
解释:(-2)2 = 4
提示:
- 0 <= n <= 109
方法一:模拟进位
思路与算法
对于「二进制数」我们可以很直观地得到以下结论:
- 对于 2i,如果 i 为偶数时,此时 2i = (−2)i;
- 对于 2i,如果 i 为奇数时,此时 2i = (−2)i+1 + (−2)i;
因此自然可以想到将 n 转换为 −2 的幂数和,即此时 n= ∑i=0m\sum_{i=0}^m∑i=0m C×(−2)i,由于 −2 进制的每一位只能为 0 或 1,需要对每一位进行加法「进位」运算即可得到完整的「负二进制」数。对于「负二进制」数,此时需要思考一下进位规则。对于 C×(−2)i,期望得到如下变换规则:
-
如果 C 为奇数则需要将等式变为 C × (−2)i = a × (−2)i+1 + (−2)i,此时第 i 位为 1,第 i + 1 位需要加上 a;
-
如果 C 为偶数则需要将等式变为 C × (−2)i = a × (−2)i+1 ,此时第 i 位为 0,第 i + 1 位需要加上 a;
根据以上的变换规则,只需要求出 a 即可。假设当前数位上的数字为 val,当前的位上保留的余数为 r,在 x 进制下的进位为 a,根据「进位」的运算规则可知 val = a × x + r,此时可以得到进位 a = val−rx\frac{val - r} {x}xval−r。根据题意可知,「负二进制」数的每一位上保留的余数为 0 或 1,因此可以计算出当前的余数 r,由于在有符号整数的均采用补码表示,最低位的奇偶性保持不变,因此可以直接取 val 的最低位即可,此时可以得到 r = val & 1。根据上述等式可以知道,当前数位上的数字为 val 时,此时在「负二进制」下向高位的进位为 a = val−(val&1)−2\frac{val - (val \& 1)} {-2}−2val−(val&1) 。
基于以上进位规则,将变换出来的数列进行进位运算即可得到完整的「负二进制」数。整个转换过程如下:
- 将 n 转换为二进制数,并将二进制数中的每一位转换为「负二进制」中的每一位,变换后的数列为 bits;
- 将 bits 从低位向高位进行「进位」运算,即将 bits 中的每一位都变为 0 或者 1;
- 去掉前导 0 以后,将 bits 转换为字符串返回即可。
代码:
class Solution {
public:string baseNeg2(int n) {if (n == 0) {return "0";}vector<int> bits(32);for (int i = 0; i < 32 && n != 0; i++) {if (n & 1) {bits[i]++;if (i & 1) {bits[i + 1]++;}}n >>= 1;}int carry = 0;for (int i = 0; i < 32; i++) {int val = carry + bits[i];bits[i] = val & 1;carry = (val - bits[i]) / (-2);}int pos = 31;string res;while (pos >= 0 && bits[pos] == 0) {pos--;}while (pos >= 0) {res.push_back(bits[pos] + '0');pos--;}return res;}
};
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.9 MB, 在所有 C++ 提交中击败了33.33%的用户
复杂度分析
时间复杂度:O( C ),其中 C = 32。需要对 n 转换为二进制位,需要的时间复杂度为 O(logn),然后需要对其进行二进制位的中每一位进行「负二进制进位」运算,由于整数有 32 位,因此需要「负二进制进位」运算 32 次即可。
空间复杂度:O( C ),其中 C = 32。需要对 n 转换为二进制位,由于整数最多只有 32 位,在此每次采取固定的存储空间为 O(32)。
方法二:进制转换
思路与算法
当基数 x > 1 时,将整数 n 转换成 x 进制的原理是:令 n0 = n,计算过程如下:
- 当计算第 0 位上的数字时,此时 n1 = ⌊ n0x{n_0} \over xxn0⌋,n0 = n1 × x + r,其中 0 ≤ r < x;
- 当计算第 i 位上的数字时,此时 ni+1 = ⌊ nix{n_i} \over xxni ⌋,ni = ni+1 × x + r,其中 0 ≤ r < x;
按照上述计算方式进行计算,直到满足 ni = 0 结束。
如果基数 x 为负数,只要能确定余数的可能取值,上述做法同样适用。由于「负二进制」表示中的每一位都是 0 或 1,因此余数的可能取值是 0 和 1,可以使用上述做法将整数 n 转换成「负二进制」。具体转换过程如下:
- 如果 n = 0 则返回 “0",n = 1 则直接返回 “1";
- 如果 n > 1 则使用一个字符串记录余数,将整数 n 转换成「负二进制」,重复执行如下操作,直到 n = 0;
- 计算当前 n 的余数,由于当前的余数只能为 0 或 1,由于有符号整数均采用补码表示,最低位的奇偶性保持不变,因此可以直接取 C 的最低位即可,此时直接用 n&1 即可得到最低位的余数,将余数拼接到字符串的末尾。
- 将 n 的值减去余数,然后将 n 的值除以 −2。
上述操作结束之后,将字符串翻转之后得到「负二进制」数。
代码:
class Solution {
public:string baseNeg2(int n) {if (n == 0 || n == 1) {return to_string(n);}string res;while (n != 0) {int remainder = n & 1;res.push_back('0' + remainder);n -= remainder;n /= -2;}reverse(res.begin(), res.end());return res;}
};
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.8 MB, 在所有 C++ 提交中击败了75.00%的用户
复杂度分析
时间复杂度:O(logn),其中 n 是给定的整数。整数 n 对应的「负二进制」表示的长度是 logn,需要生成「负二进制」表示的每一位。
空间复杂度:O(1)。除返回值外,不需要额外的空间。
方法三:数学计算
思路与算法
根据题意可知,32 位「负二进制」数中第 i 位则表示(−2)i,当 i 为偶数时,则 (−2)i = 2i,当 i 为奇数时,则 (−2)i = −2i ,因此可以得到其最大值与最小值分别为如下:
- 最大值即所有的偶数位全部都为 1,奇数位全为 0,最大值即为 0x55555555 = 1,431,655,765;
- 最小值即所有的偶数位全部都为 0,奇数位全为 1,最小值即为 0xAAAAAAAA = −2,863,311,530;
- 0x55555555, 0xAAAAAAAA 均为「十六进制」进制原码表示;
令 maxVal = 0x55555555,由于题目中 n 给定的范围为 0 ≤ n ≤ 109,因此一定满足 maxVal > n。设 maxVal 与 n 的差为 diff,则此时 diff = maxVal − n,如果我们将 maxVal 在「负二进制」表示下减去 diff,那么得到的「负二进制」一定为 n 的「负二进制」。已知 maxVal 中的偶数位全为 1,奇数位全为 0,此时的减法操作可以用异或来实现:
- 对于 diff 中偶数位为 1 的位,在 maxVal 中需要将其置为 0,此时 maxVal 中偶数位全部为 1,1 ⊕ 1 = 0,偶数位异或操作即可将需要的位置为 0;
- 对于 diff 中奇数位为 1 的位,在 maxVal 中需要将其置为 1,此时 maxVal 中奇数位全部为 0,0 ⊕ 1 = 1,奇数位异或操作将需要的位置为 1,
根据以上推论可以知道,「负二进制」减法等同于 maxVal ⊕ diff。按照上述方法可以知道 n 的「负二进制」数等于 ma x Val ⊕ (maxVal − n),我们求出 n 的「负二进制」数,然后将其转换为二进制的字符串即可。
代码:
class Solution {
public:string baseNeg2(int n) {int val = 0x55555555 ^ (0x55555555 - n);if (val == 0) {return "0";}string res;while (val) {res.push_back('0' + (val & 1));val >>= 1;}reverse(res.begin(), res.end());return res;}
};
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.7 MB, 在所有 C++ 提交中击败了98.15%的用户
复杂度分析
时间复杂度:O(logn),其中 n 是给定的整数。整数 n 对应的「负二进制」表示的长度是 logn,需要生成「负二进制」表示的每一位。
空间复杂度:O(1)。除返回值外,不需要额外的空间。
author:LeetCode-Solution
相关文章:
【1017. 负二进制转换】
来源:力扣(LeetCode) 描述: 给你一个整数 n ,以二进制字符串的形式返回该整数的 负二进制(base -2)表示。 注意, 除非字符串就是 "0",否则返回的字符串中不…...
C语言实现插入排序与希尔排序
目录 一,插入排序 插入排序C语言实现(升序) 1,将新元素插入到有序序列 2,循环的开始与终止 二,希尔排序 希尔排序C语言实现(升序) 1,单趟: 2&#x…...
第九章-DOM与CSS
style属性 文档中每个元素节点都有一个属性style。style属性包含着元素样式,查询这个属性将返回一个对象而不是一个简单的字符串。样式都存放在这个style对象的属性里。 var element getElementById("example") //查看颜色属性 element.style.color //…...
蓝桥杯真题练习
小蓝在玩一个寻宝游戏, 游戏在一条笔直的道路上进行, 道路被分成了 nn 个方格, 依次编号 1 至 nn, 每个方格上都有一个宝物, 宝物的分值是一个整数 (包括正数、负数和零), 当进入一个方格时即获得方格中宝物的分值。小蓝可 以获得的总分值是他从方格中获得的分值之和。 小蓝开始…...
插入排序的简单理解
详细描述 插入排序的基本思想是:将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增 1 的有序表。 在其实现过程中使用双层循环,外层循环针对除了第一个元素之外的所有元素,内层循环针对当前元素前面的有序表进行…...
Springboot框架集成Websocket通信方式
Websocket实现了“服务器”主动向“客户端”发送数据,改变了以往通过轮询、长轮训、长连接等方式获取服务器端数据的方式。 一、Websocket有三种不同的用场景,单播、广播和组播; (一)、单播(Unicast) 单播是客户端与服务器之间的“一对一”的连接。是在一个单个的发送…...
将json数据分组
在工作中有时需要根据业务需要,将大量数据进行处理分成几个一组 // 例如要将下方数据进行处理 var stuCount [{"id": "1612321835288","libraryCode": "D","regionCode": "A","positionCode&qu…...
从零开始实现一个C++高性能服务器框架----Socket模块
此项目是根据sylar框架实现,是从零开始重写sylar,也是对sylar丰富与完善 项目地址:https://gitee.com/lzhiqiang1999/server-framework 简介 项目介绍:实现了一个基于协程的服务器框架,支持多线程、多协程协同调度&am…...
ld: library not found for -lcrt0.o
ld: library not found for -lcrt0.o 背景: Mac 系统编译的时候报错 语言:golang 原因: 代码使用了静态编译,-static。stack overflow 上说 This option will not work on Mac OS X unless all libraries (including libgcc.a…...
接口测试和功能测试的区别有哪些?说一些你不知道的知识
目录 接口测试和功能测试的区别 目的 测试范围 测试方法 重要性 编辑 举个例子 对于接口测试 对于功能测试 编辑 总结 接口测试和功能测试是软件测试中的两种常见测试类型,主要用于评估软件系统的质量。尽管这两种测试都是为了评估软件系统的性…...
深度学习实战——不同方式的模型部署(CNN、Yolo)
忆如完整项目/代码详见github:https://github.com/yiru1225(转载标明出处 勿白嫖 star for projects thanks) 目录 系列文章目录 一、实验综述 1.实验工具及及内容 2.实验数据 3.实验目标 4.实验步骤 二、ML/DL任务综述与模型部署知识…...
【论文阅读】GNN阅读笔记
A gentle introduction on gnn 前言 发表在distill的文章 图神经网络在应用上才刚刚开始 搭建了一个GNN playground 什么是图 图是表示实体之间的关系 可以分别表示成点向量、边向量、图向量 图可以分为有向图和无向图 数据是怎么表示成图 图片表示成图: …...
QT常用控件——QTreeWidget(树控件),QTableWidget控件
目录 ★先开个小灶,在此插句话:【有关Halcon与Qt联编变量转换】 QTreeWidget树控件 QTableWidget控件...
为什么学校购买小型数控机床而不是大型工业数控机床?
CNC 机器是计算机控制的设备,可以高精度和准确度地切割、雕刻、钻孔或雕刻各种材料。 它们广泛应用于制造、工程、设计和艺术行业。 CNC 机器具有不同的尺寸和功能,从小型台式机到大型工业机型。 人们可能想知道为什么学校会选择购买小型 CNC 机器而不是…...
【Go自学】一文搞懂Go append方法
我们先看一下append的源码 // The append built-in function appends elements to the end of a slice. If // it has sufficient capacity, the destination is resliced to accommodate the // new elements. If it does not, a new underlying array will be allocated. //…...
【压测】通过Jemeter进行压力测试(超详细)
文章目录背景一、前言二、关于JMeter三、准备工作四、创建测试4.1、创建线程组4.2、配置元件4.3、构造HTTP请求4.4、添加HTTP请求头4.5、添加断言4.6、添加察看结果树4.7、添加Summary Report4.8、测试计划创建完成五、执行测试计划总结背景 通过SpringCloudGateway整合Nacos进…...
C# | 上位机开发新手指南(七)加密算法
上位机开发新手指南(七)加密算法 文章目录上位机开发新手指南(七)加密算法前言加密算法的分类对称加密算法和非对称加密算法流加密算法和块加密算法分组密码和序列密码哈希函数和消息认证码对称加密与非对称对称加密优点缺点对称加…...
实验一 跨VLAN访问
目录 一、按照拓扑图配置VLAN,并实现跨VLAN间的访问。 二、实验环境 三、实验步骤 一、按照拓扑图配置VLAN,并实现跨VLAN间的访问。 1、配置好交换机的VLAN和各个终端的地址,实现各个VLAN内能连通。 2、开启两个交换机的VTY连接࿰…...
通信算法之130:软件无线电-接收机架构
1. 超外差式接收机 2.零中频接收机 3.数字中频接收机...
C++编程大师之路:从入门到精通-C++基础入门
文章目录前言主要内容C基础入门初识C第一个C程序注释变量常量关键字标识符命名规则数据类型整型sizeof关键字实型(浮点型)字符型转义字符字符串型布尔类型 bool数据的输入运算符算术运算符赋值运算符比较运算符逻辑运算符程序流程结构选择结构if语句三目…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...
