剑指offer刷题记录 python

1. 数组中重复的数字

长度n,数字0-n-1

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param numbers int整型一维数组 
# @return int整型
#
class Solution:
    def duplicate(self , numbers: List[int]) -> int:
        n = len(numbers)
        for i in range(n):
            num = numbers[i]
            while num != i:
                if num < 0 or num > n-1:
                    return -1
                elif numbers[num] == num:
                    return num
                numbers[i],numbers[num] = numbers[num],numbers[i]
                num = numbers[i]
        return -1

                

引申:不修改数组,找出重复的数字

长度n+1的数组里,所有数字都在1-n范围内注意这里与上面的数字范围其实不同,只有数字区间比长度小1的时候可以这么做,上一题数字区间与长度是一样长的

方法1:用o(n)辅助空间,时间复杂度o(n)

方法2:不用辅助空间,用二分法count数字数量,时间复杂度o(nlog(n))

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param numbers int整型一维数组
# @return int整型
#
class Solution:
    def duplicate(self, numbers: list[int]) -> int:
        n = len(numbers)
        if n < 2:
            return -1
        l,r = 0,n-1
        while l < r-1:
            mid = (l + r) // 2
            numCnt = 0
            for num in numbers:
                if num <= mid:
                    numCnt += 1
            if numCnt > mid-l+1:
                r = mid
            else:
                l = mid+1
        lNumCnt,rNumCnt = 0,0
        for num in numbers:
            if num == numbers[l]:
                lNumCnt += 1
            elif num == numbers[r]:
                rNumCnt += 1
            if lNumCnt > 1:
                return numbers[l]
            if rNumCnt > 1:
                return numbers[r]
        return -1

2. 二维数组中的查找

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param target int整型 
# @param array int整型二维数组 
# @return bool布尔型
#
class Solution:
    def Find(self , target: int, array: List[List[int]]) -> bool:
        if len(array) == 0 or len(array[0]) == 0:
            return False
        m,n = len(array),len(array[0])
        # select the number on right up corner
        i,j = 0,n-1
        while array[i][j] != target:
            if array[i][j] < target:
                i += 1
            else:
                j -= 1
            if i < 0 or i > m-1 or j < 0 or j > n-1:
                return False
        return True

3. 替换空格

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param s string字符串
# @return string字符串
#
class Solution:
    def replaceSpace(self , s: str) -> str:
        # step1: 统计空格数量
        n = len(s)
        spaceCnt = 0
        for i in range(n):
            if s[i] == " ":
                spaceCnt += 1
        # 注意这里增加的数量的2倍空格,空格本身就有位置
        s = s + " " * spaceCnt * 2
        # python字符串无法修改,改成list修改
        s = list(s)
        j = len(s) - 1
        for i in range(n-1,-1,-1):
            if s[i] == " ":
                s[j],s[j-1],s[j-2] = "0","2","%"
                j -= 3
            else:
                s[j] = s[i]
                j -= 1
            print("".join(s))
        return "".join(s)

4. 从尾到头打印链表

用递归 or 栈

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param listNode ListNode类 
# @return int整型一维数组
#
class Solution:
    def printListFromTailToHead(self, listNode: ListNode) -> list[int]:
        printList = []
        if not listNode:
            return printList
        stack = []
        l = listNode
        while l:
            stack.append(l.val)
            l = l.next
        while stack:
            val = stack.pop(-1)
            printList.append(val)
        return printList     

递归

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param listNode ListNode类 
# @return int整型一维数组
#
class Solution:
    def printListFromTailToHead(self, listNode: ListNode) -> list[int]:
        if not listNode:
            return []
        if not listNode.next:
            return [listNode.val]
        printList = self.printListFromTailToHead(listNode.next)
        printList.append(listNode.val)
        return printList

5.重建二叉树

# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param pre int整型一维数组 
# @param vin int整型一维数组 
# @return TreeNode类
#
class Solution:
    def reConstructBinaryTree(self , pre: List[int], vin: List[int]) -> TreeNode:
        if len(pre) == 0:
            return None
        root = TreeNode(pre[0])
        if len(pre) == 1:
            return root

        rootIdx = 0
        for i in range(len(vin)):
            if vin[i] == pre[0]:
                rootIdx = i
                break
        
        vinLeft,vinRight = vin[0:rootIdx],vin[rootIdx+1:len(vin)]
        preLeft,preRight = pre[1:len(vinLeft)+1],pre[len(vinLeft)+1:len(pre)]
        root.left = self.reConstructBinaryTree(preLeft,vinLeft)
        root.right = self.reConstructBinaryTree(preRight,vinRight)
        return root

6.二叉树的下一个结点

# -*- coding:utf-8 -*-
# class TreeLinkNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#         self.next = None
class Solution:
    def GetNext(self, pNode):
        if not pNode:
            return None
        # 有右子树,右子树最左节点就是下个节点
        if pNode.right:
            p = pNode.right
            while p.left:
                p = p.left
            return p
        # 没有右子树,
        else:
            # 如果是父节点的左子树,则返回父节点,否则不断往上,直到满足这个条件
            p = pNode
            father = p.next
            while father and father.left != p:
                p = father
                father = p.next
            return father

7.用两个栈实现队列

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stack1 = []
        self.stack2 = []
    def push(self, node):
        self.stack1.append(node)
    def pop(self):
        if len(self.stack2) == 0:
            while len(self.stack1):
                self.stack2.append(self.stack1.pop(-1))
        if len(self.stack2):
            return self.stack2.pop(-1)
        return None

8.斐波那契数列

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param n int整型 
# @return int整型
#
class Solution:
    def Fibonacci(self , n: int) -> int:
        if n == 1 or n ==2:
            return 1
        f1,f2 = 1,1
        cur = 2
        while cur < n:
            curSum = f1+f2
            f1 = max(f1,f2)
            f2 = curSum
            cur += 1
        return f2
        

8.旋转数组的最小数字

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param rotateArray int整型一维数组
# @return int整型
#
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        if len(rotateArray) == 0:
            return None
        l,r = 0,len(rotateArray)-1

        while l+1 < r:
            mid = (l+r)//2
            if rotateArray[l] < rotateArray[mid]:
                l = mid
            elif rotateArray[l] > rotateArray[mid]:
                r = mid
            # 2,2,2,1,2
            # 2,1,2,2,2
            else:
                if rotateArray[r] < rotateArray[mid]:
                    l = mid
                    # 这里只能r走,否则出现顺序情况会无法判断
                while rotateArray[l] == rotateArray[r] and l < r:
                    r -= 1
        # 数组完全是顺序的情况
        return min(min(rotateArray[l],rotateArray[r]),rotateArray[0])

反向写,相对来说不容易卡边界,但是我会有点想不清楚

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param rotateArray int整型一维数组
# @return int整型
#
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        if len(rotateArray) == 0:
            return None
        l,r = 0,len(rotateArray)-1

        while l+1 < r:
            mid = (l+r)//2
            if rotateArray[r] < rotateArray[mid]:
                l = mid
            elif rotateArray[r] > rotateArray[mid]:
                r = mid
            # 2,2,2,1,2
            # 2,1,2,2,2
            else:
                if rotateArray[l] < rotateArray[mid]:
                    return rotateArray[l]
                elif rotateArray[l] > rotateArray[mid]:
                    r = mid
                while rotateArray[l] == rotateArray[r] and l < r:
                    l += 1
                    r -= 1
        # 数组完全是顺序的情况
        return min(rotateArray[l],rotateArray[r])

9.矩阵中的路径

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param matrix char字符型二维数组
# @param word string字符串
# @return bool布尔型
#
class Solution:
    def __init__(self):
        self.direction = [[-1,0],[1,0],[0,1],[0,-1]]

    def hasPath(self , matrix: list[list[str]], word: str) -> bool:
        if len(matrix) == 0 or len(matrix[0]) == 0:
            return False

        self.lenX = len(matrix)
        self.lenY = len(matrix[0])
        self.matrix = matrix
        self.word = word
        self.visited = [[0 for j in range(self.lenY)] for i in range(self.lenX)]

        for i in range(self.lenX):
            for j in range(self.lenY):
                if self.dfs(i,j,0):
                    return True
        return False

    def dfs(self,x,y,n):
        if n == len(self.word):
            return True
        # 注意不要漏掉x < 0 or y < 0的判断
        if x < 0 or y < 0 or x >= self.lenX or y >= self.lenY or self.matrix[x][y] != self.word[n] or self.visited[x][y]:
            return False

        self.visited[x][y] = 1
        for i,j in self.direction:
            if self.dfs(x+i,y+j,n+1):
                return True

        self.visited[x][y] = 0
        return False

10.机器人的运动范围

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param threshold int整型
# @param rows int整型
# @param cols int整型
# @return int整型
#
class Solution:
    def __init__(self):
        self.direction = [[-1,0],[1,0],[0,1],[0,-1]]

    def movingCount(self , threshold: int, rows: int, cols: int) -> int:
        if not rows or not cols or threshold < 0:
            return 0
        self.rows = rows
        self.cols = cols
        self.visited = [[0 for i in range(cols)] for j in range(rows)]
        self.squireCnt = 0
        self.dfs(0,0,threshold)
        return self.squireCnt

    def dfs(self,x,y,threshold):
        if x >= self.rows or y >= self.cols or x < 0 or y < 0 or self.visited[x][y] == 1 or not self.checkNum(x,y,threshold):
            return
        self.visited[x][y] = 1
        self.squireCnt += 1
        for i,j in self.direction:
            self.dfs(x+i,y+j,threshold)

    def checkNum(self,x,y,threshold):
        xysum = 0
        while x:
            xysum += x%10
            x //= 10
        while y:
            xysum += y%10
            y //= 10
        if xysum > threshold:
            return False
        else:
            return True

11.剪绳子

注意不要漏余数为0的判断

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param number int整型
# @return int整型
#
class Solution:
    def cutRope(self , number: int) -> int:
        # 8:2,3,3
        # 10:1,3,3,3/2,3,3,2
        cnt3 = number//3
        remain = number%3
        # 注意不要漏余数为0的判断
        if remain == 0:
            return pow(3,cnt3)
        elif remain == 1:
            return 4 * pow(3,cnt3-1)
        else:
            return 2 * pow(3,cnt3)

12.二进制中1的个数

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param n int整型 
# @return int整型
#
class Solution:
    def NumberOf1(self , n: int) -> int:
        flag = 1
        cnt = 0
        for i in range(32):
            if flag & n:
                cnt += 1
            flag <<= 1
        return cnt

13.数值的整数次方

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param base double浮点型
# @param exponent int整型
# @return double浮点型
#
class Solution:
    def Power(self , base: float, exponent: int) -> float:
        if base == 0:
            return 0
        if exponent == 0 or base == 1:
            return 1
        isNeg = False
        if exponent < 0:
            isNeg = True
        result = 1
        exp = abs(exponent)
        for i in range(exp):
            result *= base
        if isNeg:
            return 1.0/result
        return result

快速幂,具体解法参考之前文章

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param base double浮点型
# @param exponent int整型
# @return double浮点型
#
class Solution:
    def Power(self , base: float, exponent: int) -> float:
        if base == 0:
            return 0
        if exponent == 0 or base == 1:
            return 1
        isNeg = False
        if exponent < 0:
            isNeg = True
        result = 1
        exp = abs(exponent)
        while exp:
            if exp & 1:
                result *= base
            base *= base
            exp = exp >> 1
        if isNeg:
            return 1.0/result
        return result

 14.删除链表的节点

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param head ListNode类 
# @param val int整型 
# @return ListNode类
#
class Solution:
    def deleteNode(self , head: ListNode, val: int) -> ListNode:
        dummy = ListNode(-1)
        dummy.next = head
        p = dummy
        while p.next:
            if p.next.val == val:
                p.next = p.next.next
            p = p.next
        return dummy.next

 15.正则表达式匹配

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param str string字符串
# @param pattern string字符串
# @return bool布尔型
#
class Solution:
    def match(self, s: str, pattern: str) -> bool:
        # 记忆化搜索
        self.isVisited = [[0 for j in range(len(pattern)+1)] for i in range(len(s)+1)]
        # [i+1][j+1]保存从i,j开始的字符串是否匹配
        self.MatchList = [[False for j in range(len(pattern)+1)] for i in range(len(s)+1)]
        # 当两个字符串都是空串时
        self.MatchList[0][0] = True
        return self.isMatch(s,pattern,0,0)

    def isMatch(self,s,p,i,j):
        if j >= len(p):
            return i >= len(s)
        if i >= len(s):
            if j < len(p) and p[j] == "*":
                return self.isMatch(s,p,i,j+1)
            if j+1 < len(p) and p[j+1] == "*":
                return self.isMatch(s,p,i,j+2)
            return j >= len(p)

        if self.isVisited[i+1][j+1]:
            return self.MatchList[i+1][j+1]
        self.isVisited[i + 1][j + 1] = 1

        if j+1 < len(p) and p[j+1] == "*":
            if s[i] == p[j] or p[j] == ".":
                # 匹配0次,1次
                self.MatchList[i+1][j+2] = self.isMatch(s,p,i,j+2) or self.isMatch(s,p,i+1,j+2) or self.isMatch(s,p,i+1,j)
            else:
                # 匹配0次
                self.MatchList[i + 1][j + 2] = self.isMatch(s,p,i,j+2)
            return self.MatchList[i + 1][j + 2]
        elif s[i] == p[j] or p[j] == ".":
            self.MatchList[i+1][j+1] = self.isMatch(s,p,i+1,j+1)
            return self.MatchList[i+1][j+1]

        return False

16.表示数值的字符串

注意需要记录当前3种状态,是否有过数字,exp和dot

class Solution:
    def isNumeric(self, s: str) -> bool:
        symbols = ["+", "-"]
        exp = ["E","e"]
        dot = "."
        hasDot = False
        hasExp = False
        hasNum = False

        s = s.strip()

        if not len(s):
            return False

        for i in range(len(s)):
            # 注意不能把这两个if合并, 否则会导致正常有符号的字符串走到最后的else,导致return False
            if s[i] in symbols:
                if i != 0 and s[i-1] not in exp or i == len(s)-1:
                    return False
            elif s[i] in exp:
                if hasExp or not hasNum or i == 0 or i == len(s)-1:
                    return False
                hasExp = True
            elif s[i] == dot:
                if hasDot or hasExp or (i == len(s)-1 and not hasNum):
                    return False
                hasDot = True
            elif s[i].isdigit():
                hasNum = True
            else:
                return False
        return True

17.调整数组顺序使奇数位于偶数前面

O(N)时间,O(N)空间

class Solution:
    def reOrderArray(self , array: List[int]) -> List[int]:
        newArray = [0 for i in range(len(array))]
        oddCnt = 0
        for num in array:
            if num & 1:
                oddCnt += 1
        i,j = 0,oddCnt
        for num in array:
            if num & 1:
                newArray[i] = num
                i += 1
            else:
                newArray[j] = num
                j += 1
        return newArray

O(N^2)时间,O(1)空间

class Solution:
    def reOrderArray(self , array: List[int]) -> List[int]:
        l,r = 0,0
        while l < len(array) and r < len(array):
            while l < len(array) and array[l] & 1:
                l += 1
            # 找到需要放在l位置的下一个奇数
            r = l
            while r < len(array) and not array[r] & 1:
                r += 1
            # 冒泡
            while l < len(array) and r < len(array) and r > l:
                array[r-1],array[r] = array[r],array[r-1]
                r -= 1
        return array

18.链表中倒数最后k个结点

class Solution:
    def FindKthToTail(self , pHead: ListNode, k: int) -> ListNode:
        if not pHead:
            return None
        dummy = ListNode(-1)
        dummy.next = pHead
        p,kNode = dummy,dummy
        for i in range(k):
            if p:
                p = p.next
        if not p:
            return None
        while p:
            p = p.next
            kNode = kNode.next
        return kNode

19.链表中环的入口结点

x: head到环起点

y:环起点到快慢指针首次相遇点

z:相遇点到环起点

m,n两个指针相遇前分别绕环到圈数

2(x+m(y+z)+y) = x+n(y+z)+y

x = (n-m)(y+z)-y

所以快慢指针相遇后,让两个指针分别从头和相遇点开始,再次相遇点为环起点

class Solution:
    def EntryNodeOfLoop(self, pHead):
        if not pHead:
            return pHead
        fast,slow = pHead,pHead
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                p,q = pHead,fast
                while p != q:
                    p = p.next
                    q = q.next
                return p
        return None

20.反转链表

头插法

class Solution:
    def ReverseList(self , head: ListNode) -> ListNode:
        dummy = ListNode(-1)
        dummy.next = head
        pre = head
        while pre and pre.next:
            tmp = pre.next
            pre.next = pre.next.next
            tmp.next = dummy.next
            dummy.next = tmp
        return dummy.next

递归

class Solution:
    def ReverseList(self , head: ListNode) -> ListNode:
        if not head or not head.next:
            return head
        pre = self.ReverseList(head.next)
        p = pre
        while p.next:
            p = p.next
        head.next = None
        p.next = head
        return pre

21.合并两个排序的链表

class Solution:
    def Merge(self , pHead1: ListNode, pHead2: ListNode) -> ListNode:
        dummy = ListNode(-1)
        pre = dummy
        p,q = pHead1,pHead2
        while p and q:
            if p.val < q.val:
                pre.next = p
                p = p.next
            else:
                pre.next = q
                q = q.next
            pre = pre.next
        if q:
            p = q
        pre.next = p
        return dummy.next

22.树的子结构

class Solution:
    def HasSubtree(self, pRoot1: TreeNode, pRoot2: TreeNode) -> bool:
        if not pRoot1 or pRoot2:
            return False
        return self.isSub(pRoot1,pRoot2)

    def isSub(self, pRoot1: TreeNode, pRoot2: TreeNode):
        if not pRoot1:
            return pRoot2 == None
        if not pRoot2:
            return True
        if pRoot1.val == pRoot2.val and self.isSub(pRoot1.left,pRoot2.left) and self.isSub(pRoot1.right,pRoot2.right):
            return True
        return self.isSub(pRoot1.left,pRoot2) or self.isSub(pRoot1.right,pRoot2)

23.二叉树的镜像

class Solution:
    def Mirror(self , pRoot: TreeNode) -> TreeNode:
        if pRoot:
            pRoot.left,pRoot.right = pRoot.right,pRoot.left
            self.Mirror(pRoot.left)
            self.Mirror(pRoot.right)
        return pRoot

24.对称的二叉树

class Solution:
    def isSymmetrical(self, pRoot: TreeNode) -> bool:
        if not pRoot:
            return True
        return self.isSym(pRoot.left,pRoot.right)

    def isSym(self,p,q):
        if not p or not q:
            return p == None and q == None
        if p.val == q.val:
            return self.isSym(p.left,q.right) and self.isSym(p.right,q.left)
        return False

26.包含min函数的栈

(单调栈) O(1)
我们除了维护基本的栈结构之外,还需要维护一个单调栈,来实现返回最小值的操作。
下面介绍如何维护单调栈:

当我们向栈中压入一个数时,如果该数 ≤ 单调栈的栈顶元素,则将该数同时压入单调栈中;否则,不压入,这是由于栈具有先进后出性质,所以在该数被弹出之前,栈中一直存在一个数比该数小,所以该数一定不会被当做最小数输出。
当我们从栈中弹出一个数时,如果该数等于单调栈的栈顶元素,则同时将单调栈的栈顶元素弹出。
单调栈由于其具有单调性,所以它的栈顶元素,就是当前栈中的最小数。
时间复杂度
四种操作都只有常数次入栈出栈操作,所以时间复杂度都是 O(1).

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.minStack = []
        self.singleStack = []

    def push(self, node):
        self.minStack.append(node)
        if not self.singleStack or self.singleStack[-1] >= node:
            self.singleStack.append(node)

    def pop(self):
        if not self.minStack:
            return None
        if self.minStack[-1] == self.singleStack[-1]:
            self.singleStack.pop(-1)
        self.minStack.pop(-1)

    def top(self):
        if not self.minStack:
            return None
        return self.minStack[-1]

    def min(self):
        if not self.minStack:
            return None
        return self.singleStack[-1]

27.顺时针打印矩阵

class Solution:
    def printMatrix(self , matrix: List[List[int]]) -> List[int]:
        if not matrix or not matrix[0]:
            return []
        m,n=len(matrix),len(matrix[0])
        visited = [[0 for i in range(len(matrix[0]))] for j in range(len(matrix))]
        direction = [[0,1],[1,0],[0,-1],[-1,0]]
        result = []
        i,j,d = 0,0,0

        for cnt in range(m*n):
            result.append(matrix[i][j])
            visited[i][j] = 1
            if i+direction[d][0] == m or j+direction[d][1] == n or visited[i+direction[d][0]][j+direction[d][1]]:
                d = (d+1)%4
            i = i+direction[d][0]
            j = j+direction[d][1]
        return result

28.栈的压入、弹出序列

class Solution:
    def IsPopOrder(self, pushV: List[int], popV: List[int]) -> bool:
        stack = []
        i = 0
        for j in range(len(popV)):
            if stack and stack[-1] == popV[j]:
                stack.pop(-1)
            else:
                while i < len(pushV) and pushV[i] != popV[j]:
                    stack.append(pushV[i])
                    i += 1
                if i >= len(pushV):
                    return False
                i += 1
        return True

更清晰的思路

class Solution:
    def IsPopOrder(self, pushV: List[int], popV: List[int]) -> bool:
        if len(pushV) != len(popV):
            return False
        stack = []
        j = 0
        for i in range(len(pushV)):
            stack.append(pushV[i])
            while stack and j < len(popV) and stack[-1] == popV[j]:
                stack.pop(-1)
                j += 1
        return len(stack) == 0

29.二叉搜索树的后序遍历序列

class Solution:
    def VerifySquenceOfBST(self , sequence: List[int]) -> bool:
        if len(sequence) == 1:
            return True
        root = sequence[-1]
        left,right = [],[]
        for num in sequence:
            if num < root:
                if not right:
                    left.append(num)
                else:
                    return False
            else:
                right.append(num)
        return self.VerifySquenceOfBST(left) and self.VerifySquenceOfBST(right)

30.二叉树中和为某一值的路径(二)

class Solution:
    def __init__(self):
        self.allPaths = []

    def FindPath(self , root: TreeNode, target: int) -> List[List[int]]:
        if not root:
            return []
        self.target = target
        self.isPath(root,[],0)
        return self.allPaths

    def isPath(self,node,path,pathSum):
        pathSum += node.val
        path.append(node.val)
        if not node.left and not node.right:
            if pathSum == self.target:
                self.allPaths.append(path.copy())
        if node.left:
            self.isPath(node.left,path,pathSum)
        if node.right:
            self.isPath(node.right, path, pathSum)
        path.pop(-1)

31.复杂链表的复制

# -*- coding:utf-8 -*-
# class RandomListNode:
#     def __init__(self, x):
#         self.label = x
#         self.next = None
#         self.random = None
        
class Solution:
    # 返回 RandomListNode
    def Clone(self, pHead):
        if not pHead:
            return None
        nodeDict = {}
        node = RandomListNode(pHead.label)
        nodeDict[pHead] = node
        newHead,p = node,pHead
        while p:
            if p.next:
                if p.next not in nodeDict:
                    newNode = RandomListNode(p.next.label)
                    nodeDict[p.next] = newNode
                node.next = nodeDict[p.next]
            if p.random:
                if p.random not in nodeDict:
                    newNode = RandomListNode(p.random.label)
                    nodeDict[p.random] = newNode
                node.random = nodeDict[p.random]
            p = p.next
            node = node.next
        return newHead

32.二叉搜索树与双向链表

中序遍历

# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

#
#
# @param pRootOfTree TreeNode类
# @return TreeNode类
#
class Solution:
    def Convert(self , pRootOfTree ):
        if not pRootOfTree:
            return None
        p = pRootOfTree
        stack = []
        pre,head = None,None
        isfirst = True
        while p or stack:
            if p:
                stack.append(p)
                p = p.left
            else:
                p = stack.pop(-1)
                if isfirst:
                    head = p
                    isfirst = False
                if pre:
                    pre.right = p
                    p.left = pre
                pre = p
                p = p.right
        return head

序列化二叉树

# # -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Serialize(self, root):
        queue,strList,p = [root],[],root
        while queue:
            p = queue.pop(0)
            if p:
                strList.append(str(p.val))
                queue.append(p.left)
                queue.append(p.right)
            else:
                strList.append("#")
        return ",".join(strList)

    def Deserialize(self, s):
        strList = s.split(",")
        if strList[0] == "#":
            return None
        root = TreeNode(int(strList[0]))
        queue = [root]
        i = 1
        while queue:
            p = queue.pop(0)
            if strList[i] != "#":
                left = TreeNode(int(strList[i]))
                queue.append(left)
                p.left = left
            i += 1
            if strList[i] != "#":
                right = TreeNode(int(strList[i]))
                queue.append(right)
                p.right = right
            i += 1
        return root

38.字符串排列

输入一个字符串,打印出该字符串中字符的所有排列。

你可以以任意顺序返回这个字符串数组,但里面不能有重复元素

示例:

输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]

class Solution:
    def permutation(self, s):
        self.result = []
        self.visited = [0 for _ in range(len(s))]
        s = list(s)
        s.sort()
        self.s = s
        self.dfs("")
        return self.result

    def dfs(self, permut):
        if len(permut) == len(self.s):
            self.result.append(permut)
            return
        i = 0
        for i in range(len(self.s)):
            # 去重
            # self.visited[i] == 1: 上一层已经访问过
            # self.visited[i] == 0: 本层已被访问过,又被置零
            if i > 0 and self.s[i] == self.s[i - 1] and not self.visited[i - 1]:
                continue
            if not self.visited[i]:
                self.visited[i] = 1
                self.dfs(permut + self.s[i])
                self.visited[i] = 0

39. 数组中出现次数超过一半的数字

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
限制:

1 <= 数组长度 <= 50000

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return -1
        halfNum = nums[0]
        cnt = 1
        for num in nums[1:]:
            if cnt == 0:
                cnt += 1
                halfNum = num
            elif num == halfNum:
                cnt += 1
            else:
                cnt -= 1
        return halfNum

(*) 40. 最小的k个数

注意快排练习,又写错了

class Solution(object):
    def getLeastNumbers(self, arr, k):
        """
        :type arr: List[int]
        :type k: int
        :rtype: List[int]
        """
        if k > len(arr) or k <= 0:
            return []
        pivot = -1
        l,r = 0,len(arr)-1
        while pivot != k-1:
            pivot = self.getPivot(arr,l,r)
            if pivot > k-1:
                r = pivot-1
            else:
                l = pivot+1
        return arr[:k]
            
    def getPivot(self,arr,l,r):
        pivot = arr[l]
        while l < r:
            while l < r and arr[r] >= pivot:
                r -= 1
            arr[l], arr[r] = arr[r], arr[l]
            while l < r and arr[l] <= pivot:
                l += 1
            arr[l],arr[r] = arr[r],arr[l]
        arr[l] = pivot
        return l


堆排:大顶堆

class Solution(object):
    def getLeastNumbers(self, arr, k):
        if k < 1 or k > len(arr):
            return []
        
        heap = arr[:k]
        for i in range(k//2,-1,-1):
            self.adjust(heap,i)
        for num in arr[k:]:
            if num < heap[0]:
                heap[0] = num
                self.adjust(heap,0)
        return heap

    def adjust(self, arr, idx):
        maxIdx = idx
        if 2*idx+1 < len(arr) and arr[2*idx+1] > arr[maxIdx]:
            maxIdx = 2*idx+1
        if 2*idx+2 < len(arr) and arr[2*idx+2] > arr[maxIdx]:
            maxIdx = 2*idx+2
        if maxIdx != idx:
            arr[idx], arr[maxIdx] = arr[maxIdx], arr[idx]
            self.adjust(arr, maxIdx)

剑指 Offer 41. 数据流中的中位数

注意下python heap只有小顶堆

class MedianFinder(object):
    def __init__(self):
        """
        initialize your data structure here.
        """
        self.minHeap, self.maxHeap = [],[]

    def addNum(self, num):
        """
        :type num: int
        :rtype: None
        """
        if not self.maxHeap or num < -self.maxHeap[0]:
            heappush(self.maxHeap,-num)
        else:
            heappush(self.minHeap,num)

        if len(self.maxHeap) + 2 == len(self.minHeap):
            heappush(self.maxHeap, -heappop(self.minHeap))
        elif len(self.minHeap) + 2 == len(self.maxHeap):
            heappush(self.minHeap,-heappop(self.maxHeap))

    def findMedian(self):
        """
        :rtype: float
        """
        if not self.maxHeap and not self.minHeap:
            return None
        if len(self.maxHeap) == len(self.minHeap):
            return (-self.maxHeap[0]+self.minHeap[0]+0.0)/2
        if len(self.maxHeap) > len(self.minHeap):
            return -self.maxHeap[0]
        else:
            return self.minHeap[0]

剑指 Offer 42. 连续子数组的最大和

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return None
        maxSum,curSum = nums[0],nums[0]
        for num in nums[1:]:
            curSum = max(num,curSum+num)
            maxSum = max(maxSum, curSum)
        return maxSum

(*) 剑指 Offer 43. 1~n 整数中 1 出现的次数

每有1个10,个位就会有1个1

个位1的个数是

n/10+(n%10>1? 1:0)

每有1个100就会有10个1在十位上

十位1的个数是

n/100*10+(n%100>10? min(10,n%100-10+1):0)

注意不能直接n/10,会存在100/10=0而100/100*10=19这种情况

class Solution(object):
    def countDigitOne(self, n):
        """
        :type n: int
        :rtype: int
        """
        exp = 10
        base = 1
        oneCnt = 0
        while exp <= n*10:
            oneCnt += (n//exp*base + min(max(n%exp-base+1,0),base))
            base = exp
            exp *= 10
        return oneCnt

(*) 剑指 Offer 44. 数字序列中某一位的数字

这题我想不清楚

class Solution(object):
    def findNthDigit(self, n):
        """
        :type n: int
        :rtype: int
        """
        base = 9
        length = 1
        curSum = 0
        while curSum + length*base < n:
            curSum += length*base
            length += 1
            base *= 10
        curNum = pow(10,length-1)+(n-curSum-1)//length
        curBit = (n-curSum-1)%length
        return int(str(curNum)[curBit])

剑指 Offer 45. 把数组排成最小的数

class Solution(object):
    def minNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: str
        """
        return ''.join(sorted(map(str, nums), key=cmp_to_key(lambda x, y: -(x+y <= y+x))))

剑指 Offer 46. 把数字翻译成字符串

dp

class Solution(object):
    def translateNum(self, num):
        """
        :type num: int
        :rtype: int
        """
        num = str(num)
        n = len(num)
        dp = [0 for i in range(n)]
        dp[0] = 1
        for i in range(1,n):
            dp[i] = dp[i-1]
            cur = int(num[i-1:i+1])
            if num[i-1] != "0" and cur <= 25:
                if i-2 < 0:
                    dp[i] += 1
                else:
                    dp[i] += dp[i-2]
        return dp[n-1]

剑指 Offer 47. 礼物的最大价值

class Solution(object):
    def maxValue(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        if not len(grid) or not len(grid[0]):
            return 0
        m,n = len(grid),len(grid[0])
        dp = [[0]*(n+1)]*(m+1)
        for i in range(m):
            for j in range(n):
                dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j])+grid[i][j]
        return dp[m][n]

剑指 Offer 48. 最长不含重复字符的子字符串

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        l = 0
        idxDict = {}
        maxLen = 0
        for i in range(len(s)):
            if s[i] not in idxDict or idxDict[s[i]] < l:
                idxDict[s[i]] = i
                maxLen = max(maxLen,i-l+1)
            else:
                l = idxDict[s[i]] + 1
                idxDict[s[i]] = i
        return maxLen

剑指 Offer 49. 丑数

class Solution(object):
    def nthUglyNumber(self, n):
        """
        :type n: int
        :rtype: int
        """
        i2,i3,i5 = 0,0,0
        nums = [1]
        for i in range(1,n):
            n2 = nums[i2]*2
            n3 = nums[i3] * 3
            n5 = nums[i5] * 5
            num = min(n2,min(n3,n5))
            nums.append(num)
            if num == n2:
                i2 += 1
            if num == n3:
                i3 += 1
            if num == n5:
                i5 += 1
        return nums[n-1]

剑指 Offer 50. 第一个只出现一次的字符

class Solution(object):
    def firstUniqChar(self, s):
        """
        :type s: str
        :rtype: str
        """
        letters = {}
        uiqIdx = len(s)
        uiqChar = " "
        for i in range(len(s)):
            if s[i] not in letters:
                letters[s[i]] = i
            else:
                letters[s[i]] = -1
        for char,idx in letters.items():
            if idx != -1 and idx < uiqIdx:
                uiqIdx = idx
                uiqChar = char
        return uiqChar

剑指 Offer 51. 数组中的逆序对(*)

归并排序

class Solution(object):
    def reversePairs(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        self.pairs = 0
        self.MergeSort(nums,0,len(nums)-1)
        return self.pairs

    def MergeSort(self,nums,l,r):
        if l >= r:
            return
        if l+1 == r:
            if nums[l] > nums[r]:
                nums[l],nums[r] = nums[r],nums[l]
                self.pairs += 1
                return
        mid = (l+r)//2
        self.MergeSort(nums,l,mid)
        self.MergeSort(nums,mid+1,r)
        self.Merge(nums,l,r)

    def Merge(self,nums,l,r):
        result = []
        mid = (l + r) // 2
        i,j = l,mid+1
        while i <= mid and j <= r:
            if nums[i] <= nums[j]:
                result.append(nums[i])
                i += 1
            else:
                result.append(nums[j])
                # 这儿注意不只是一对
                self.pairs += (mid-i+1)
                j += 1
        # 这儿不需要再计数了
        while i <= mid:
            result.append(nums[i])
            i += 1
        while j <= l:
            result.append(nums[j])
            j += 1
        i = l
        for num in result:
            nums[i] = num
            i += 1

剑指 Offer 52. 两个链表的第一个公共节点

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        if not headA or not headB:
            return None
        p,q = headA,headB
        lenA,lenB = 0,0
        while p:
            lenA += 1
            p = p.next
        while q:
            lenB += 1
            q = q.next
        p,q = headA,headB
        while lenA > lenB:
            p = p.next
            lenA -= 1
        while lenB > lenA:
            q = q.next
            lenB -= 1
        while p != q:
            p = p.next
            q = q.next
        return p

剑指 Offer 53 - I. 在排序数组中查找数字 I(*)

二分法

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        l,r = 0,len(nums)-1
        while l <= r:
            mid = (l+r)//2
            # 注意这里是<,寻找下边界
            if nums[mid] < target:
                l = mid+1
            else:
                r = mid-1
        start = l
        l,r = 0,len(nums)-1
        while l <= r:
            mid = (l+r)//2
            # 这里是<=,寻找上边界
            if nums[mid] <= target:
                l = mid+1
            else:
                r = mid-1
        end = r
        return end-start+1

剑指 Offer 53 - II. 0~n-1中缺失的数字

class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        l,r = 0,len(nums)-1
        while l < r:
            mid = (l+r)//2
            if nums[mid] == mid:
                l = mid+1
            else:
                r = mid-1
        if l == nums[l]:
            return l+1
        return l

剑指 Offer 54. 二叉搜索树的第k大节点

中序遍历

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

class Solution(object):
    def kthLargest(self, root, k):
        """
        :type root: TreeNode
        :type k: int
        :rtype: int
        """
        if not root:
            return None
        p = root
        stack = []
        nodeCnt = 0
        while p or stack:
            if p:
                stack.append(p)
                p = p.right
            else:
                p = stack.pop(-1)
                nodeCnt += 1
                if nodeCnt == k:
                    return p.val
                p = p.left

剑指 Offer 55 - I. 二叉树的深度

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

class Solution(object):
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        return max(self.maxDepth(root.left),self.maxDepth(root.right))+1

剑指 Offer 55 - II. 平衡二叉树(*)

从根结点开始递归,防止反复计算

class Solution(object):
    def isBalanced(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True
        if self.getDepth(root) == -1:
            return False
        return True

    def getDepth(self,root):
        if not root:
            return 0
        leftDepth = self.getDepth(root.left)
        rightDepth = self.getDepth(root.right)
        # 核心就是这行
        if leftDepth == -1 or rightDepth == -1 or abs(leftDepth-rightDepth) > 1:
            return -1
        return 1+max(leftDepth, rightDepth)

剑指 Offer 56 - I. 数组中数字出现的次数(*)

在一个数组中除了一个数字只出现一次之外,其他数字都出现了三次。

请找出那个只出现一次的数字。

你可以假设满足条件的数字一定存在。

class Solution(object):
    def singleNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        flag = 0
        for num in nums:
            flag ^= num

        diff = 1
        while not diff & flag:
            diff <<= 1
        
        nums_1,nums_2,result = [],[],[]
        for num in nums:
            if num & diff:
                nums_1.append(num)
            else:
                nums_2.append(num)
        num1,num2 = 0,0
        for num in nums_1:
            num1 ^= num
        for num in nums_2:
            num2 ^= num
        return [num1,num2]

剑指 Offer 56 - II. 数组中数字出现的次数 II(*)

一个int一共32位,统计每一位上1出现的次数,如果能被3整除,则出现1次那个数在该位上为0,否则为1

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        result = 0
        for i in range(32):
            flag = 1 << i
            cnt = 0
            for num in nums:
                if num & flag:
                    cnt += 1
            if cnt % 3 == 1:
                result ^= flag
        return result

剑指 Offer 57. 和为s的两个数字

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        l,r = 0,len(nums)-1
        while l < r:
            if nums[l]+nums[r] == target:
                return [nums[l],nums[r]]
            elif nums[l]+nums[r] < target:
                l += 1
            else:
                r -= 1
        return []

剑指 Offer 57 - II. 和为s的连续正数序列(*)

import copy
class Solution(object):
    def findContinuousSequence(self, target):
        """
        :type target: int
        :rtype: List[List[int]]
        """
        num = 1
        results,res,cursum = [],[],0
        while num < target:
            cursum += num
            res.append(num)
            while cursum > target:
                cursum -= res.pop(0)
            if cursum == target:
                results.append(copy.copy(res))
            num += 1
        return results

剑指 Offer 58 - I. 翻转单词顺序

class Solution(object):
    def reverseWords(self, s):
        """
        :type s: str
        :rtype: str
        """
        s = [char.strip() for char in s.strip().split(" ") if len(char)]
        return " ".join(s[::-1])

剑指 Offer 58 - II. 左旋转字符串

class Solution(object):
    def reverseLeftWords(self, s, n):
        """
        :type s: str
        :type n: int
        :rtype: str
        """
        res = [s[i] for i in range(n,len(s))]
        for i in range(0,n):
            res.append(s[i])
        return "".join(res)

剑指 Offer 59 - I. 滑动窗口的最大值(*)

单调队列

from collections import deque

class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        if k >= len(nums):
            return [max(nums)]
        queue,result = deque(),[]
        for i in range(len(nums)):
            while queue and queue[0] < i-k+1:
                queue.popleft()
            while queue and nums[queue[-1]] < nums[i]:
                queue.pop()
            queue.append(i)
            if i >= k-1:
                result.append(nums[queue[0]])
        return result

剑指 Offer 59 - II. 队列的最大值(*)

同上

from collections import deque

class MaxQueue(object):

    def __init__(self):
        self.queue = deque()
        self.maxQueue = deque()

    def max_value(self):
        """
        :rtype: int
        """
        if not self.maxQueue:
            return -1
        return self.maxQueue[0]

    def push_back(self, value):
        """
        :type value: int
        :rtype: None
        """
        self.queue.append(value)
        while self.maxQueue and self.maxQueue[-1] < value:
            self.maxQueue.pop()
        self.maxQueue.append(value)

    def pop_front(self):
        """
        :rtype: int
        """
        if not self.queue:
            return -1
        if self.maxQueue[0] == self.queue[0]:
            self.maxQueue.popleft()
        return self.queue.popleft()



# Your MaxQueue object will be instantiated and called as such:
# obj = MaxQueue()
# param_1 = obj.max_value()
# obj.push_back(value)
# param_3 = obj.pop_front()

剑指 Offer 60. n个骰子的点数(*)

class Solution(object):
    def dicesProbability(self, n):
        """
        :type n: int
        :rtype: List[float]
        """
        dp = [1.0 / 6] * 6
        for i in range(2, n + 1):
            tmp = [0] * (5 * i + 1)
            for j in range(len(dp)):
                for k in range(6):
                    tmp[j+k] += dp[j]/6
            dp = tmp
        return dp

剑指 Offer 61. 扑克牌中的顺子(*)

用0的数量去判断是否是顺子

class Solution(object):
    def isStraight(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        if not nums or len(nums) < 5:
            return False
        zeroCnt = 0
        nums.sort()
        for i in range(len(nums)):
            if nums[i] == 0:
                zeroCnt += 1
            elif i > 0 and nums[i-1] != 0:
                flag = nums[i]-nums[i-1]-1
                if flag < 0:
                    return False
                else:
                    zeroCnt -= flag
        return zeroCnt >= 0

剑指 Offer 62. 圆圈中最后剩下的数字(*)

class Solution(object):
    def lastRemaining(self, n, m):
        """
        :type n: int
        :type m: int
        :rtype: int
        """
        if n == 0:
            return 0
        return (self.lastRemaining(n-1,m)+m)%n

剑指 Offer 63. 股票的最大利润(*)

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        profit,cost = 0,float("+inf")
        for price in prices:
            cost = min(cost,price)
            profit = max(profit,price-cost)
        return profit

剑指 Offer 64. 求1+2+…+n

class Solution(object):
    def sumNums(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n == 1:
            return 1
        return n+self.sumNums(n-1)

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

class Solution(object):
    def add(self, a, b):
        """
        :type a: int
        :type b: int
        :rtype: int
        """
        while b != 0:
            c = a&b << 1
            a^=b
            b=c
        return a

剑指 Offer 66. 构建乘积数组

class Solution(object):
    def constructArr(self, a):
        """
        :type a: List[int]
        :rtype: List[int]
        """
        if not a:
            return []
        n = len(a)
        pre, back, b = [0] * n, [0] * n, [0] * n
        pre[0] = a[0]
        back[-1] = a[-1]
        for i in range(1, n):
            pre[i] = pre[i - 1] * a[i]
        for i in range(n - 2, 0, -1):
            back[i] = back[i + 1] * a[i]
        for i in range(1, n - 1):
            b[i] = back[i + 1] * pre[i - 1]
        b[0] = back[1]
        b[-1] = pre[n - 2]
        return b

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

class Solution(object):
    def strToInt(self, s):
        """
        :type str: str
        :rtype: int
        """
        s = s.strip()
        if not s:
            return 0
        res,sign,i = 0,1,0
        intMax,intMin,bundary = pow(2,31)-1,-pow(2,31),pow(2,31)//10
        if s[0] == "-" or s[0] == "+":
            if s[0] == "-":
                sign = -1
            i = 1
        for c in s[i:]:
            if not (c >= "0" and c <= "9"):
                break
            if res > bundary or (res >= bundary and c > "7"):
                if sign == 1:
                    return intMax
                return intMin
            res = res*10+(ord(c)-ord("0"))
        return res*sign

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

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

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        if p.val > q.val:
            p,q = q,p
        while root:
            if root.val > q.val:
                root = root.left
            elif root.val < p.val:
                root = root.right
            else:
                break
        return root

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

核心:最近公共祖先一定是p,q在这个节点的两侧

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

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        if not root or root == p or root == q:
            return root
        left = self.lowestCommonAncestor(root.left,p,q)
        right = self.lowestCommonAncestor(root.right,p,q)
        if not left: return right
        if not right: return left
        return root # 当 left和 right均不为空时,说明 p、q节点分别在 root异侧, 最近公共祖先即为 root

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值