剑指offer 65 至 剑指offer 68 - II 题解

Posted 风去幽墨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer 65 至 剑指offer 68 - II 题解相关的知识,希望对你有一定的参考价值。

剑指 Offer 65. 不用加减乘除做加法

题意:

写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。

题解:

先思考两个正数相加。
a+b 在二进制下一共只有四种情况 + 进位情况。

  • 0 + 0 = 0
  • 0 +1 = 1 + 0 = 1
  • 1+ 1 = 0 进位1

很容易得出,加法后本位结果就是异或的结果,而是否进位的结果是相与的结果。
所以a+b = (a^b)+(a&b)<<1.
很容易就能够写出递归表达式。
while b !=0
a, b = (a ^ b), (a & b) << 1
接下来就是注意python里的负数以及变量无位数限制的情况。
整型中0xffffffff是32位二进制全为1的情况,其中若是最高位为1则表示负数。
在处理时加上判断即可。

代码:

class Solution:
    def add(self, a: int, b: int) -> int:
        x = 0xffffffff
        a, b = a & x, b & x
        while b != 0:
            a, b = (a ^ b), (a & b) << 1 & x
        return a if a <= 0x7fffffff else ~(a ^ x)

剑指 Offer 66. 构建乘积数组

题意:

给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。

题解:

预处理一下前缀积和后缀积

代码:

class Solution:
    def constructArr(self, a: List[int]) -> List[int]:
        sum,rsum= [1]*(len(a)+1),[1]*(len(a)+2)
        for i in range(1,len(a)+1):
            sum[i] =sum[i-1]*a[i-1]
        for i in range(len(a),0,-1):
            rsum[i]=rsum[i+1]*a[i-1]
        ret = []
        for i in range(1,len(a)+1):
            ret.append(sum[i-1]*rsum[i+1])
        return ret

剑指 Offer 67. 把字符串转换成整数

题意:

字符串转换成整数

题解:

字符串处理问题,注意各种非法值即可。

代码:

class Solution:
    def strToInt(self, str: str) -> int:
        s,st,ans = str.strip(),0,0
        INT_MAX,INT_MIN = (1<<31)-1,-(1<<31)
        if len(s)== 0:return 0
        if s[0]=='+' or s[0]=='-':
            st+=1
        if len(s)==1 and st == 1:
            return 0
        for i in range(st,len(s)):
            if '0'<=s[i]<='9':
                ans=ans*10+int(s[i])
            else:
                break
        if st == 1 and s[0]=='-':
            ans = -ans
        ans = min(ans,INT_MAX)
        ans = max(ans,INT_MIN)
        return ans

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

题意:

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先

题解:

因为是二叉搜索树,所以满足左子树<根节点<右子树。
所以两个节点的最小公共祖先,一定满足 :
min(q.val,p.val)<=root.val<=max(q.val,p.val)
且满足此要求的节点为最近公共祖先。
反证:若是节点A满足此要求但不是最近公共祖先,那么节点p与节点q应该分布在其左右子树上且不在同一子树上,或者有一节点为根节点A本身。此时最近公共祖先B应该在A的左右子树之一中,那么根据有序性B无法满足上述要求,故节点A为最近公共祖先。

代码:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root: return None
        def dfs(root:'TreeNode'):
            if min(q.val,p.val)<=root.val<=max(q.val,p.val):
                return root
            elif root.val>=max(q.val,p.val):
                return dfs(root.left)
            else :
                return dfs(root.right)
        return dfs(root)

剑指 Offer 68 - II. 二叉树的最近公共祖先

题意:

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

题解:

递归寻找,记录左右子树是否含有p或者q节点。
当前节点为最近公共祖先的成立条件是:

  • 左右子树包含pq节点
  • 左右子树之一包含pq节点之一,该节点本身为pq节点之一

代码:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
        ans=None
        def dfs(root:TreeNode)->bool:
            nonlocal ans
            if not root:return False
            fl = dfs(root.left)
            fr = dfs(root.right)
            if (fl and fr) or ((root == p or root == q) and(fl or fr)):
                ans =root
            if root == p or root == q :
                return True
            return fl or fr
        dfs(root)
        return ans

以上是关于剑指offer 65 至 剑指offer 68 - II 题解的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer 65 至 剑指offer 68 - II 题解

剑指offer(65)

剑指offer系列——剑指 Offer 65. 不用加减乘除做加法

剑指offer 面试65题

剑指 Offer 68 二叉树的最近公共祖先

乱序版 ● 剑指offer每日算法题打卡题解——位运算 (题号15,16,65)