Leetcode 面试题 17.01 不用加号的加法

设计一个函数把两个数字相加。不得使用 + 或者其他算术运算符。

示例:

输入: a = 1, b = 1
输出: 2

提示:

  • ab 均可能是负数或 0
  • 结果不会溢出 32 位整数

我的答案:

一、信息

1.设计一个函数把两个数相加

2.不得使用+或者其他运算符

3.a,b均为负数或0

4.结果不会溢出32位整数

二、分析

问题出现:

1.如何实现不用加法就实现两数相加呢?

我的思路:

思路1:通过将a,b转化成二进制,这样我们就能用二进制加法求解了。

新的问题出现:

该如何实现二进制加法呢?

首先我们可以观察二进制加法的规律

  1101

+1010

 10111

规律就是:

1 0 得1

1 1 得0

0 0 得0

我的答案其实很简单我们只需要通过与异或运算即可实现

问题2:该如何避免结果不会溢出32位整数呢?

我的实现:

为了不使用`+`或其他算术运算符来实现数字的加法,我们可以使用位操作。以下是基于此思路的解决方案:

### 1. C语言:

#include <stdio.h>int add(int a, int b) {while (b != 0) {unsigned int carry = (unsigned int)(a & b) << 1; // 计算进位a = a ^ b;  // 不计算进位的加法b = carry; // 把进位放在b上,继续进行加法}return a;
}int main() {int a = 1, b = 1;printf("Sum: %d\n", add(a, b));return 0;
}

2. C++:

#include <iostream>int add(int a, int b) {while (b != 0) {unsigned int carry = (unsigned int)(a & b) << 1;a = a ^ b;b = carry;}return a;
}int main() {int a = 1, b = 1;std::cout << "Sum: " << add(a, b) << std::endl;return 0;
}

JAVA:

public class AddWithoutPlus {public static int add(int a, int b) {while (b != 0) {int carry = a & b;  // 计算进位a = a ^ b;  // 不计算进位的加法b = carry << 1;  // 把进位放在b上,继续进行加法}return a;}public static void main(String[] args) {int a = 1, b = 1;System.out.println("Sum: " + add(a, b));}
}

 

这些解决方案都是基于二进制表示的加法原理,利用位操作来实现的。当我们加两个二进制数时,可以分为两步:1) 不计算进位的加法,和 2) 计算进位。

英雄师傅的分析:

将a和b都转化成二进制以后,执行相加,举个简单的例子,例如a是21(二进制是10101),b是12(二进制是1100),它们两个相加的值应该是33

对于两个数的对应相加,如果不产生进位就是异或的结果。(在我看来就是用异或来模拟这个过程)

比如说:

唯一没有提到的,就是1和1相加的情况,这种情况会产生进位,所以异或结果并不等于相加的结果,但是异或的结果等于相加后低位的值。换言之1+1=10,异或结果等于0,0和0相等,很合理。

基于上述观点,如果两个数二进制在相加的过程中,都没有出现1和1的情况,那么加法就等于两个数的异或。如果有进位,那么就要把进位的那部分单独拎出来。

什么时候有进位呢?当两个都为1的时候,也就是两个位与为1的时候,所以我们可以把a+b拆成两个部分 

a^b和a&b

英雄师傅的实现过程:

int add(int a, int b){if(b==0){return a;}return add(a^b,((unsigned int)(a&b))<<1);
}

Leetcode 题解

Leetcode地址:Leetcode题解

方法一:位运算
预备知识

有符号整数通常用补码来表示和存储,补码具有如下特征:

正整数的补码与原码相同;负整数的补码为其原码除符号位外的所有位取反后加 111。

可以将减法运算转化为补码的加法运算来实现。

符号位与数值位可以一起参与运算。

思路和算法

虽然题目只要求了不能使用算术运算符,但是原则上来说也不宜使用类似的运算符 +=\texttt{+=}+= 和 -=\texttt{-=}-= 以及 sum\texttt{sum}sum 等方法。于是,我们使用位运算来处理这个问题。

首先,考虑两个二进制位相加的四种情况如下:

0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 0 (进位)
可以发现,对于整数 aaa 和 bbb:

在不考虑进位的情况下,其无进位加法结果为 a⊕b\texttt{a} \oplus \texttt{b}a⊕b。

而所有需要进位的位为 a & b\texttt{a \& b}a & b,进位后的进位结果为 (a & b) << 1\texttt{(a \& b) << 1}(a & b) << 1。

于是,我们可以将整数 aaa 和 bbb 的和,拆分为 aaa 和 bbb 的无进位加法结果与进位结果的和。因为每一次拆分都可以让需要进位的最低位至少左移一位,又因为 aaa 和 bbb 可以取到负数,所以我们最多需要 log⁡(max_int)\log (max\_int)log(max_int) 次拆分即可完成运算。

因为有符号整数用补码来表示,所以以上算法也可以推广到 000 和负数。

实现

在 C++\texttt{C++}C++ 的实现中,当我们赋给带符号类型一个超出它表示范围的值时,结果是 undefined\text{undefined}undefined;而当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模的余数。因此,我们可以使用无符号类型来防止溢出。

在 Python\texttt{Python}Python 的实现中,因为 Python\texttt{Python}Python 的整数类型为是无限长的,所以无论怎样左移位都不会溢出。因此,我们需要对 Python\texttt{Python}Python 中的整数进行额外处理,以模拟用补码表示的 323232 位有符号整数类型。具体地,我们将整数对 2322^{32}2 
32
  取模,从而使第 333333 位及更高位均为 000;因为此时最终结果为用补码表示的包含符号位的 323232 位整数,所以我们还需要再次将其换算为 Python\texttt{Python}Python 的整数。

C++:

class Solution {
public:int add(int a, int b) {while (b != 0) {unsigned int carry = (unsigned int)(a & b) << 1;a = a ^ b;b = carry;}return a;}
};

JAVA:

class Solution {public int add(int a, int b) {while (b != 0) {int carry = (a & b) << 1;a = a ^ b;b = carry;}return a;}
}

 

总结:

个人

从这个问题中,我们可以学到多方面的知识和技能:

1. **基础计算机科学知识**:这道题目介绍了如何使用位操作来模拟基本的算术运算,这反映了计算机在底层如何处理加法。

2. **递归和迭代思维**:即使在这样的问题中,递归和迭代的应用也是一个重要的思维模式。我们反复应用相同的逻辑,直到达到预期的结果。

3. **处理边界情况**:考虑到整数溢出和32位限制,这提醒我们在解决问题时总是要注意潜在的边界情况和限制。

4. **位操作技能**:位操作是许多算法和数据结构问题中的一个关键技能。这道题目为我们提供了一次实际应用的机会,加深了我们对`AND`、`XOR`、左移等操作的理解。

5. **创新思维**:当面对某些明显的方法(例如使用加法运算符)不可用时,寻找其他解决方案需要创新思维。这种思维方式对于不断发展的计算机科学领域是至关重要的。

6. **优化和效率**:尽管我们可以使用递归来解决此问题,但递归可能会导致效率问题,特别是对于大的整数。这提醒我们,即使某个方法是可行的,我们仍然需要考虑其效率。

7. **实际应用与理论知识**:在真实的计算机系统中,加法和其他算术操作确实是通过硬件逻辑(例如加法器)和位操作来实现的。通过这种方法,我们不仅学习了一种算法技巧,而且还深入了解了计算机的工作原理。

总的来说,这道题目为我们提供了一次深入学习计算机科学基础、算法设计和优化的机会,并激发了我们的创新思维。

感受:

其实这道题目和计算机组成原理中定点加法和减法这一章很像,象在哪里呢?其实就是像在对二进制加法的推导和探索,其中二者都处理了很多进位问题。其实我觉得出题人是想让我们体验一把当初计算机科学家们是如何一步一步设计出加法器的,就是绕开编译器原本就带着的+法函数而是自己写一个这个函数的底层。

(传送门:计算机组成原理 2.2 定点加法)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/64490.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

企业工程项目管理系统源码-专注项目数字化管理-Java工程管理-二次开发

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…

什么是 Web 应用程序安全测试?

Web 应用程序安全测试是一种严格的实践&#xff0c;旨在识别、分析和纠正基于 Web 的应用程序中的漏洞。 此过程涉及使用一套全面的工具和方法来评估 Web 应用程序的安全性和完整性。它包括渗透测试、漏洞评估和代码审查等实践。 Web 应用程序安全测试的主要目标是阻止潜在的…

沃尔玛,eBay买家号成号率低如何解决?

eBay是一个很庞大的系统&#xff0c;买家号必须在本土环境才会安全。要想养出高权重的买家号&#xff0c;需要花大量的时间跟精力&#xff0c;一旦养出一批高质量且时间周期较长的买家号&#xff0c;就可以做很多事情&#xff0c;比如可以帮产品上排名&#xff0c;提高产品的权…

2020ICPC南京站

K K Co-prime Permutation 题意&#xff1a;给定n和k&#xff0c;让你构造n的排列&#xff0c;满足gcd(pi, i)1的个数为k。 思路&#xff1a;因为x和x-1互质&#xff0c;1和任何数互质&#xff0c;任何数和它本身不互质 当k为奇数时&#xff0c;p11&#xff0c;后面k-1个数…

python3.11教程2:基础数据类型(数字和字符串)、组合数据类型(集合、元组、列表、字典)

文章目录 五、基本数据类型5.1 整数和浮点数5.1.1 整数和浮点数的类型5.1.2 进制和进制转换5.1.3 round函数 5.2 运算符5.2.1 常用运算符、运算符函数和逻辑运算符5.2.2 位运算符5.2.3 运算符的优先级及其进阶使用 5.3 布尔类型5.4 字符串5.3.1 字符串的基本操作5.3.2 字符串函…

CAN总线学习——物理层、数据链路层、CANopen协议

1、CAN总线介绍 1.1、CAN总线描述 (1)CAN总线支持多节点通信&#xff0c;但是节点不分区主从&#xff0c;也就是不存在一个节点来负责维护总线的通信&#xff1b;这点可以和I2C总线对对比&#xff0c;I2C是一主多从模式&#xff1b; (2)是差分、异步、串行总线&#xff0c;采用…

Android安卓实战项目(13)---记账APP详细记录每天的收入和支出并且分类统计【生活助手类APP】强烈推荐自己也在用!!!(源码在文末)

Android安卓实战项目&#xff08;13&#xff09;—记账APP详细记录每天的收入和支出并且分类统计【生活助手类APP】强烈推荐自己也在用&#xff01;&#xff01;&#xff01;&#xff08;源码在文末&#x1f415;&#x1f415;&#x1f415;&#xff09; 一.项目运行介绍 B站…

说说HTTP 和 HTTPS 有什么区别?

分析&回答 http协议 超文本传输协议&#xff0c;是互联网上应用最多的协议&#xff0c;基于TCP/IP通讯协议来传递信息&#xff0c;用于从WWW服务器传输超文本到本地浏览器的传输协议。 https协议 我们可以将其看作是以安全为目标的http协议。在http协议的基础上增加了S…

C++——vector:resize与reserve的区别,验证写入4GB大数据时相比原生操作的效率提升

resize和reserve的区别 reserve&#xff1a;预留空间&#xff0c;但不实例化元素对象。所以在没有添加新的对象之前&#xff0c;不能引用容器内的元素。而要通过调用push_back或者insert。 resize&#xff1a;改变容器元素的数量&#xff0c;且会实例化对象&#xff08;指定或…

十一、MySQL(DQL)聚合函数

1、聚合函数 注意&#xff1a;在使用聚合函数时&#xff0c;所有的NULL是不参与运算的。 2、实际操作&#xff1a; &#xff08;1&#xff09;初始化表格 &#xff08;2&#xff09;统计该列数据的个数 基础语法&#xff1a; select count(字段名) from 表名; &#xff1b;统…

【Axure高保真原型】多图表动态切换

今天和大家分享多图表动态切换的原型模板&#xff0c;点击不同的图标可以动态切换对应的表&#xff0c;包括柱状图、条形图、饼图、环形图、折线图、曲线图、面积图、阶梯图、雷达图&#xff1b;而且图表数据可以在左侧表格中动态维护&#xff0c;包括增加修改和删除&#xff0…

TiDB同城双中心监控组件高可用方案

作者&#xff1a; Prest13 原文来源&#xff1a; https://tidb.net/blog/44b9b8b1 背景 在双中心部署tidb dr-auto sync集群&#xff0c;出于监控的高可用考虑&#xff0c;在物理分离的两个数据中心分别部署独立的prometheusalertmanagergrafana&#xff0c;实现任一监控均…

基于单片机的点阵电子显示屏上下左右移加减速系统

一、系统方案 本设计的任务就是完成一个1616的点阵设计&#xff0c;并能滚动显示“********************”内容。 主要内容是&#xff0c;能同时流动显示汉字&#xff1b;能实现显示汉字无闪烁&#xff1b;能实屏幕亮度较高。本LED显示屏能够以动态扫描的方式显示一个1616点阵汉…

前端Vue仿企查查 天眼查知识产权标准信息列表组件

引入Vue仿企查查天眼查知识产权标准信息列表组件 随着技术的不断发展&#xff0c;传统的开发方式使得系统的复杂度越来越高。在传统开发过程中&#xff0c;一个小小的改动或者一个小功能的增加可能会导致整体逻辑的修改&#xff0c;造成牵一发而动全身的情况。为了解决这个问题…

flutter plugins插件【二】【FlutterAssetsGenerator】

2、FlutterAssetsGenerator 介绍地址&#xff1a;https://juejin.cn/post/6898542896274735117 配置assets目录 ​ 插件会从pubspec.yaml文件下读取assets目录&#xff0c;因此要使用本插件&#xff0c;你需要在pubspec.yaml下配置资源目录 flutter:# The following line ens…

YOLOV8模型使用-检测-物体追踪

这个最新的物体检测模型&#xff0c;很厉害的样子&#xff0c;还有物体追踪的功能。 有官方的Python代码&#xff0c;直接上手试试就好&#xff0c;至于理论&#xff0c;有想研究在看论文了╮(╯_╰)╭ 简单介绍 YOLOv8 中可用的模型 YOLOv8 模型的每个类别中有五个模型用于检…

Bert和LSTM:情绪分类中的表现

一、说明 这篇文章的目的是评估和比较 2 种深度学习算法&#xff08;BERT 和 LSTM&#xff09;在情感分析中进行二元分类的性能。评估将侧重于两个关键指标&#xff1a;准确性&#xff08;衡量整体分类性能&#xff09;和训练时间&#xff08;评估每种算法的效率&#xff09;。…

Mac不想用iTerm2了怎么办

这东西真是让人又爱又恨&#xff0c;爱的是它的UI还真不错&#xff0c;恨的是它把我的环境给破坏啦&#xff01;让我每次启动终端之后都要重新source激活我的python环境&#xff0c;而且虚拟环境前面没有括号啦&#xff01;这怎么能忍&#xff01;在UI和实用性面前我断然选择实…

React笔记(三)类组件(1)

一、组件的概念 使用组件方式进行编程&#xff0c;可以提高开发效率&#xff0c;提高组件的复用性、提高代码的可维护性和可扩展性 React定义组件的方式有两种 类组件&#xff1a;React16.8版本之前几乎React使用都是类组件 函数组件:React16.8之后&#xff0c;函数式组件使…

ebay测评,物理环境与IP环境:解决平台风控问题的关键

近期eBay平台出现了大量风控问题&#xff0c;导致许多买家账号受到影响。实际上&#xff0c;这主要是由于环境搭建方面存在主要问题。时至2023年&#xff0c;许多人的技术方案仍停留在几年前&#xff0c;要么使用一键新机工具配合国外IP&#xff0c;要么使用指纹浏览器配合国外…