2022-4-28 第二期 二进制加法与不用加减乘除做加法

本文介绍了在不使用加减乘除运算符的情况下如何进行加法计算,包括二进制加法、链表表示的加法以及字符串形式的加法。通过解题思路和代码模板展示了8道相关题目,涉及剑指offer、LeetCode等平台的题目,例如字符串相加、链表相加、二进制字符串求和等,深入理解加法的本质和实现方法。
摘要由CSDN通过智能技术生成


前言

本专栏汇总刷题过程中一些相似度极高的数道题的思考逻辑,欢迎大家指出宝贵意见!


提示:以下是本篇文章正文内容,下面案例可供参考

一、题目大意

  基本主体是两个非负整数(字符串或数组形式),求二者的和。
  LC题目标号较多,由低到高排序为:

二、解题思路

1.不用加减乘除做加法

   - 剑指offer 65 不用加减乘除做加法
  使用逻辑运算符 异或(^)、与(&)进行求解。
  注意:a、b可能为0或负数,要求结果不会溢出32位整数
  具体步骤看代码及其注释,代码源于LC的K神,其讲解非常详细可以点击链接学习:

//代码粘贴处
class Solution:
    def add(self, a: int, b: int) -> int:
        x = 0xffffffff
        # python特色 用于获取补码
        a,b = a&x,b&x
        while b != 0:
        	# 非进位位 (a^b) 
        	# 进位位 (a&b) << 1 & x
            a,b = (a^b),(a&b) << 1 & x
        return a if a <= 0x7fffffff else ~(a^x)

2.二进制加法

  剑指offer II 002 二进制加法
  2 两数相加
  67 二进制求和
  415 字符串相加
  989 数组形式的整数加法
  上述四道题,都可以参考一个典型的模板进行解题,代码参考了LC的老汤大佬的,可以点击链接加深学习!
下面将对每道题进行详细阐述

  1. 剑指offer II 002 二进制加法
  • 题意:两个字符串格式的二进制数字相加。注:每个字符串仅有‘0’和‘1’组成;字符串a、b的长度位于闭区间[1,10^4];字符串若不为‘0’,则都不含前导零,即不存在‘01’的情况。
  • 解题思路:依次取出各字符串的每一位,进行进位和非进位运算。
  • 代码:
class Solution:
    def addBinary(self, a: str, b: str) -> str:
        ans = ""
        n1,n2,carry = len(a)-1,len(b)-1,0
        while n1>=0 or n2>=0:
        	# 依次取出各位 
            x = ord(a[n1]) - ord('0') if n1>=0 else 0
            y = ord(b[n2]) - ord('0') if n2>=0 else 0
            sum = x+y+carry
            # 保存非进位位
            ans += str(sum%2)
            # 保存进位位
            carry = sum//2
            n1,n2 = n1-1,n2-1
        if carry != 0: ans += str(carry)
        return ans[::-1]
  1. 2 两数相加
  • 题意:两个非空链表,表示两个非负整数,逆序存储,且每个节点存储一位数字。注:每个链表长度在[1,100]内;节点值属于[0,9];不存在前导零。简单用一个列表表示一下:
    在这里插入图片描述
  • 解题思路:与上题一样的思路,不过注意链表的特有数据结构哦!
  • 代码:
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        # 定义 头与当前指针
        head = cur = ListNode(-1)
        carry = val = 0

        while carry or l1 or l2:
            val = carry
            if l1:
                # 记住交换是同时间完成的,即 val记录的是当前l1.val
                l1,val = l1.next,l1.val+val
            if l2:
                l2,val = l2.next,l2.val+val
            carry,val = divmod(val,10)
            cur.next = cur = ListNode(val)
        return head.next
  1. 67 二进制求和
class Solution:
    def addBinary(self, a: str, b: str) -> str:
        ans = ""
        num1,num2 = a,b
        i,j,carry = len(num1)-1,len(num2)-1,0
        while i>=0 or j>=0:
            n1 = int(num1[i]) if i>=0 else 0
            n2 = int(num2[j]) if j>=0 else 0
            tmp = n1+n2+carry
            carry = tmp // 2
            ans = str(tmp%2)+ans
            i,j = i-1,j-1
        return "1"+ans if carry else ans
  1. 415 字符串相加
class Solution:
    def addStrings(self, num1: str, num2: str) -> str:
        res = ""
        i,j,carry = len(num1)-1,len(num2)-1,0
        while i>=0 or j>=0:
            n1 = int(num1[i]) if i>=0 else 0
            n2 = int(num2[j]) if j>=0 else 0
            tmp = n1+n2+carry
            carry = tmp //10
            res = str(tmp%10)+res
            i,j = i-1,j-1
        return "1"+res if carry else res
  1. 989 数组形式的整数加法
  • 题意:与415 字符串相加非常相似,不过换成了十进制。有稍微不同的地方强调一下:返回整数且输入k也是一个整数。
  • 代码:
class Solution:
    def addToArrayForm(self, num: List[int], k: int) -> List[int]:
        ans = []
        i,carry = len(num)-1,0
        while i>=0 or k!=0:
            n1 = num[i] if i >= 0 else 0
            n2 = k % 10 if k != 0 else 0
            tmp = n1+n2+carry
            carry = tmp //10
            ans.append(tmp % 10)
            i,k = i-1,k//10
        if carry != 0: ans.append(carry)
        return ans[::-1]

3.样本扩展

  43 字符串相乘
  66 加一
  先简单归纳一下,不用加减乘除的加法从较为底层上去理解加法,无非两部分一部分是进位位,另一个则是非进位位,后续的四道题则除了考虑加法的两部分运算外,更需要根据实际情况获取相加的各位,这样说来有些模糊,做一下上面两道题就更加清晰了。

  1. 43 字符串相乘
  • 题意:两个字符串形式的非负整数相乘,返回字符串形式的乘积。注:不能使用任何内置的BigInteger库或直接将输入转化为整数;字符串长度位于[1,200];字符串仅由数字组成;都不包含签到零。
  • 解题思路:按照数字位了两个字符串,令其分别相乘再相加,
  • 代码:
class Solution:
    def multiply(self, num1: str, num2: str) -> str:
        if num1 == '0' or num2 == '0': return '0'
        l1,l2 = [],[]
        n1,n2 = len(num1)-1,len(num2)-1

        for i in num1:
            l1.append(int(i)*10**n1)
            n1 -= 1
        for j in num2:
            l2.append(int(j)*10**n2)
            n2 -= 1
        ans = 0
        for i in l1:
            for j in l2:
                ans += i*j
        return str(ans)
  1. 66 加一
  • 题意:给一个列表形式的非负整数加一。注:列表的每一位均为[0,9]的整数;不存在前导零;列表长度属于[1,100]。
  • 解题思路:依次取出列表内元素,还原非负整数,加一后再进行拆解。
  • 代码:
class Solution:
    def plusOne(self, digits: List[int]) -> List[int]:
        ans,num,n = [],0,len(digits)-1
        for i in digits:
            num += i * 10**(n)
            n -= 1
        num += 1
        while num:
            ans.append(num%10)
            num //= 10
        return ans[::-1]

三、总结

  上述8道题属于典型的运算题,除了第一道题不容易想起来外,其他题均可以按照第二道题的模板思路进行解题:那便是依次取出进行加法操作的元素,分成进位位与非进位位两部分,最后进行对应输出类型的存储。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值