剑指offer题目描述+代码

剑指offer系列

1、剑指Offer 25

题目描述
在这里插入图片描述
解题思路
通过不断对比l1和l2的值的大小对链表进行添加。

代码实现

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

class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        #建立一个链表
        head=ListNode(-1)
        cur=head
        #遍历两个链表
        while l1 and l2:
            #如果l1的值大于l2
            if l1.val>l2.val:
                cur.next=l2
                l2=l2.next
            else:
                cur.next=l1
                l1=l1.next
            #比较完要移动一次指针
            cur=cur.next
        #结束后把未添加的添加进去
        cur.next=l1 if l1 else l2
        return head.next

2、剑指offer 24

题目描述
在这里插入图片描述

代码实现

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

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        pre, cur = None, head
        while cur:
            nxt = cur.next
            cur.next = pre
            pre = cur
            cur = nxt
        return pre

3、剑指offer 06

题目描述
在这里插入图片描述

解题思路
使用栈,其实就是列表,不算的用head.next遍历链表,压栈,然后直接逆序返回。
代码实现

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

class Solution:
    def reversePrint(self, head: ListNode) -> List[int]:
        stack=[]
        while head:
            stack.append(head.val)
            head=head.next
        return stack[::-1]

4、剑指offer 15

题目描述
在这里插入图片描述

解题思路
x&(x-1)可以把最低位的1消除,那么在循环中统计x&(x-1)的次数即为1的个数
代码实现

class Solution:
    def hammingWeight(self, n: int) -> int:
        count=0
        while n:
            #不断地把最低位的1变为0
            n=n&(n-1)
            count+=1
        return count

5、剑指offer 27

题目描述
在这里插入图片描述

解题思路
这道题其实和翻转二叉树是一样的,对于当前层的上一层,把左右节点交换后,再把左右节点分别作为根,递归下去,直到到达叶子节点,作为终止条件,返回。

代码实现

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

class Solution:
    def mirrorTree(self, root: TreeNode) -> TreeNode:
        #终止条件
        if not root:
            return root
        #递归
        left=self.mirrorTree(root.left)
        right=self.mirrorTree(root.right)
        #处理当前层
        root.left,root.right=right,left
        return root

6、剑指offer 32-i

题目描述
在这里插入图片描述

解题思路
栈+广度优先遍历
代码实现

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

class Solution:
    def levelOrder(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        stack=[root]
        res=[]
        while stack:
            node=stack.pop(0)
            res.append(node.val)
            if node.left:
                stack.append(node.left)
            if node.right:
                stack.append(node.right)
        return res

7、剑指offer32-ii

题目描述
在这里插入图片描述

解题思路
栈+bfs+每一层维护一个列表,返回list of list

代码实现

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

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        res=[]
        stack=[root]
        while stack:
            level=[]
            for i in range(len(stack)):
                node=stack.pop(0)
                if not node:
                    continue
                level.append(node.val)
                if node.left:
                    stack.append(node.left)
                if node.right:
                    stack.append(node.right)
            res.append(level)
        return res

8、剑指offer 32- iii

题目描述
在这里插入图片描述

解题思路
对于奇数行,从前插入,对于偶数行,从后插入
代码实现

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

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        #特殊情况
        if not root:
            return []
        #建立栈和储存结果列表
        stack,res=[root],[]
        while stack:
            level=[]
            for i in range(len(stack)):
                node=stack.pop(0)
                if not node:
                    continue
                if len(res)%2==0:
                    level.append(node.val)
                elif len(res)%2==1:
                    level.insert(0,node.val)
                if node.left:stack.append(node.left)
                if node.right:stack.append(node.right)
            res.append(level)
        return res

9、面试题30

题目描述
在这里插入图片描述

解题思路

  • A列表存储加入元素的信息
  • B列表的栈顶元素存储当前A列表的最小值
  • 当压入A的值大于B栈顶元素,更新B
  • 当A出栈值就是当前栈顶元素,对B的栈顶出栈
    代码实现
class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.A,self.B=[],[]


    def push(self, x: int) -> None:
        self.A.append(x)
        #如果b中没有元素或栈顶元素大于x
        if not self.B or self.B[-1]>=x:
            self.B.append(x)


    def pop(self) -> None:
        #当pop的元素是b的栈顶元素时
        if self.A.pop()==self.B[-1]:
            self.B.pop()


    def top(self) -> int:
        return self.A[-1]


    def min(self) -> int:
        return self.B[-1]



# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.min()

10、剑指offer 18

题目描述
在这里插入图片描述

解题思路

  • 定义指针cur,遍历整个链表,当cur.val==val时,将pre.next指向cur.next,break,如果没遇到,就pre=cur,cur=cur.next。
    代码实现
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def deleteNode(self, head: ListNode, val: int) -> ListNode:
        #特殊情况,第一个就是val
        if head.val==val:
            return head.next
        #定义当前指针和pre指针
        pre,cur=head,head.next
        #开始循环指针
        while cur:
            if cur.val==val:
                pre.next=cur.next
                break
            else:
                pre=cur
                cur=cur.next
        return head

11、剑指offer 04

题目描述
在这里插入图片描述

解题思路
从matrix右上角开始查找,往下走的值都大于当前值,往左走的值都小于当前值。
代码实现

class Solution:
    def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
        if not matrix:
            return False
        row=len(matrix)
        col=len(matrix[0])
        #定义左右指针
        r,c=0,col-1
        while r<row and c>=0:
            #如果当前元素大于target,往左移动
            if matrix[r][c]>target:
                c-=1
            elif matrix[r][c]<target:
                r+=1
            else:
                return True
        return False

12、剑指offer 55- i

题目描述
在这里插入图片描述

解题思路
就是找二叉树的最大深度,递归,如果到了叶子节点,返回深度为0,层层返回左右子树最大的深度再加1.
代码实现

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

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0

        #递归
        left=self.maxDepth(root.left)
        right=self.maxDepth(root.right)
        #选择左右最大的
        return max(left,right)+1

13、剑指offer 65

代码实现

class Solution:
    def add(self, a: int, b: int) -> int:
        res=[]
        res.append(a)
        res.append(b)
        return sum(res)

14、剑指offer 52

题目描述
在这里插入图片描述

解题思路
这道题麻烦的其实就是对于AB不相同的部分,走的路径长度不同,那么为了让他们走的路是一样的,就让a走完了从b开始走,b走完了从a开始走,保证了总路径相同,那么只要有公共节点,一定会相遇。
代码实现

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

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        node1,node2=headA,headB
        while node1!=node2:
            node1=node1.next if node1 else headB
            node2=node2.next if node2 else headA
        return node1

15、剑指offer 68-ii

代码实现

# 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:
        def dfs(root,target,path,res):
            #终止条件
            if not root:
                return
            if root==target:
                path.append(root)
                res.extend(path[:])
                return
            #当前层
            path.append(root)
            dfs(root.left,target,path,res)
            dfs(root.right,target,path,res)
            path.pop()
        res_q=[]
        res_p=[]
        dfs(root,p,[],res_p)
        dfs(root,q,[],res_q)
        #让res_q成为短的路径
        if len(res_p)>len(res_q):
            res_q,res_p=res_p,res_q
        #遍历res_p
        for i in range(len(res_p)):
            #如果不相等了
            if res_p[i]!=res_q[i]:
                return res_p[i-1]
        #如果一直没有发现,说明res_p是res_q的子路径
        return res_p[-1]

16、剑指offer 49

题目描述
在这里插入图片描述

解题思路

  • 动态规划
  • 定义了三个a,b,c表示对于当前的n使用的2,3,5的数量,因为从1,n肯定每次都只多用了一个2,一个3,或一个5。
  • 如果当前i位置对应的上一个数字的乘的来源为n2,a+=1,依次类推。

代码实现

class Solution:
    def nthUglyNumber(self, n: int) -> int:
        dp=[1]*n
        a,b,c=0,0,0
        for i in range(1,n):
            n2,n3,n5=dp[a]*2,dp[b]*3,dp[c]*5
            dp[i]=min(n2,n3,n5)
            if dp[i]==n2:
                a+=1
            if dp[i]==n3:
                b+=1
            if dp[i]==n5:
                c+=1
        return dp[n-1]

17、剑指offer 14-i

题目描述
在这里插入图片描述

解题思路
dp[i]表示对于长度为i的绳子的剪绳子后可以达到的最大的乘积,那么假设对于长度为i的绳子,剪一次得第一段为j长度,那么对于i-j的长度可以选择剪或者不剪,遍历每个i,遍历每个j,取最大的dp[i]

代码实现

class Solution:
    def cuttingRope(self, n: int) -> int:
        #建立dp
        dp=[0]*(n+1)
        #如果绳子为2,最大就是1*1
        dp[2]=1
        #开始循环
        for i in range(3,n+1):
            #在长度为i上剪第一段,剪1是无用的
            for j in range(2,i):
                dp[i]=max(dp[i],j*(i-j),j*dp[i-j])
        return dp[n]

18、剑指offer 14-ii

题目描述
在这里插入图片描述

代码实现

class Solution:
    def cuttingRope(self, n: int) -> int:
        dp=[0]*(n+1)
        dp[2]=1
        for i in range(3,n+1):
            for j in range(2,i):
                dp[i]=max(dp[i],j*(i-j),j*dp[i-j])
        return dp[n]%1000000007

19、面试题 34

题目描述
在这里插入图片描述

解题思路
这道题其实与公共祖先类似,都是要返回node的路径,只不过终止条件不同。且终止条件的判断要放在处理当前层之后。

代码实现

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def pathSum(self, root: TreeNode, target: int) -> List[List[int]]:
        #定义一个存储结果的列表
        res,path=[],[]
        def dfs(root,target):
            #终止条件
            if not root:
                return 
            #处理当前层
            path.append(root.val)
            target-=root.val
            #判断条件
            if not root.left and not root.right and not target:
                res.append(path[:])
            #递归
            dfs(root.left,target)
            dfs(root.right,target)
            path.pop()
        dfs(root,target)
        return res

20、剑指offer 54

题目描述
在这里插入图片描述

代码实现

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

class Solution:
    def kthLargest(self, root: TreeNode, k: int) -> int:
        res=[]
        def dfs(node):
            if not node:
                return
            dfs(node.right)
            res.append(node.val)
            dfs(node.left)
        dfs(root)
        return res[k-1]

优化后

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

class Solution:
    def kthLargest(self, root: TreeNode, k: int) -> int:
        self.num=0
        self.res=0
        def dfs(root):
            if not root:
                return
            dfs(root.right)
            self.num+=1
            if self.num==k:
                self.res=root.val
                return
            dfs(root.left)
        dfs(root)
        return self.res

21、剑指offer 68-i

# 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':
        def dfs(root,path,res,target):
            #终止条件
            if not root:
                return
            #判断条件
            if root==target:
                path.append(root)
                res.extend(path[:])
            #当前层
            path.append(root)
            #递归
            dfs(root.left,path,res,target)
            dfs(root.right,path,res,target)
            path.pop()

        q_list=[]
        p_list=[]
        dfs(root,[],p_list,p)
        dfs(root,[],q_list,q)
        if len(p_list)>len(q_list):
            p_list,q_list=q_list,p_list
        for i in range(len(p_list)):
            if p_list[i]!=q_list[i]:
                return p_list[i-1]
        return p_list[-1]

方法2

# 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':
        node=root
        while node:
            if node.val>p.val and node.val>q.val:
                node=node.left
            elif node.val<p.val and node.val<q.val:
                node=node.right
            else:
                return node

22、剑指offer 33

题目描述
在这里插入图片描述

代码实现

class Solution:
    def verifyPostorder(self, postorder: List[int]) -> bool:
        def dfs(i,j):
            #终止条件
            if i>=j:
                return True
            #找到当前根节点j得左子树区间和右子树区间的分割位置
            p=i
            while postorder[p]<postorder[j]:
                p+=1
            #分割点
            m=p
            #找到右子树区间
            while postorder[p]>postorder[j]:
                p+=1
            return p==j and dfs(i,m-1) and dfs(m,j-1)
        return dfs(0,len(postorder)-1)

23、剑指offer 36

题目描述
在这里插入图片描述

代码实现

"""
# Definition for a Node.
class Node:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
"""
class Solution:
    def treeToDoublyList(self, root: 'Node') -> 'Node':
        if not root:
            return
        self.pre=None
        def dfs(cur):
            if not cur:
                return
            dfs(cur.left)
            if self.pre:
                #将pre右边指向cur,cur得左边指向pre
                self.pre.right,cur.left=cur,self.pre
            else:
                #指向头节点
                self.head=cur
            #保存/移动一位
            self.pre=cur
            dfs(cur.right)
        dfs(root)
        #头节点得左边指向尾节点,尾节点的右边指向头节点
        self.head.left,self.pre.right=self.pre,self.head
        return self.head

24、剑指offer 60

题目描述
在这里插入图片描述

代码实现

class Solution:
    def dicesProbability(self, n: int) -> List[float]:
        #建立dp,对应的是第i个骰子的点数为j的方案数
        dp=[[0]*(6*n+1) for _ in range(n+1)]
        #初始化
        for i in range(1,7):
            dp[1][i]=1
        #遍历所有的骰子
        for i in range(2,n+1):
            #遍历所有的可能的值
            for j in range(i,6*i+1):
                #遍历每一种可能
                for k in range(1,7):
                    #如果当前可行解减去当前骰子数大于上一轮最小可行解
                    if j-k>=i-1:
                        dp[i][j]+=dp[i-1][j-k]
                    else:
                        break
        #所有可能的方案
        total=6**n
        res=[]
        for i in range(n,6*n+1):
            res.append(dp[n][i]/total)
        return res

25、剑指offer 43

题目描述
在这里插入图片描述

代码实现

class Solution:
    def countDigitOne(self, n: int) -> int:
        #初始化位因子,高位,当前位,最低位,结果
        res=0
        digit=1
        high=n//10
        cur=n%10
        low=0
        #开始循环
        while high!=0 or cur!=0:
            #如果当前位为0
            if cur==0:
                res+=high*digit
            elif cur==1:
                res+=high*digit+low+1
            else:
                res+=(high+1)*digit
            #开始前往下一轮
            low+=cur*digit
            cur=high%10
            high=high//10
            digit=digit*10
        return res

26、剑指offer 42

老生常谈的简单dp了
代码实现

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        max_res,pre=nums[0],0
        cur=nums[0]
        #开始循环
        for i in range(len(nums)):
            if nums[i]+pre>=nums[i]:
                cur=nums[i]+pre
            else:
                cur=nums[i]
            if max_res<cur:
                max_res=cur
            pre=cur
        return max_res

27、剑指offer 63

题目描述
在这里插入图片描述

代码实现

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if not prices:
            return 0
        n=len(prices)
        cost=prices[0]
        #建立dp
        dp=[0]*(n)
        for i in range(1,n):
            #更新cost
            cost=min(cost,prices[i])
            #对于第i天,要么什么都不做,要么卖出
            dp[i]=max(dp[i-1],prices[i]-cost)
        return dp[-1]

28、剑指offer 58-i

题目描述
在这里插入图片描述

解题思路

class Solution:
    def reverseWords(self, s: str) -> str:
        res=[]
        stack=s.split()
        while stack:
            word=stack.pop()
            res.append(word)
        return " ".join(res)

29、剑指offer 12

题目描述
在这里插入图片描述

解题思路

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        row=len(board)
        col=len(board[0])
        #定义递归函数
        def dfs(i,j,k):
            #终止条件
            if k==len(word):
                return True
            #处理当前层
            for r,c in [(i+1,j),(i,j+1),(i-1,j),(i,j-1)]:
                if 0<=r<row and 0<=c<col and board[r][c]==word[k]:
                    board[r][c]="/"
                    if dfs(r,c,k+1):
                        return True
                    board[r][c]=word[k]
            return False

        for i in range(row):
            for j in range(col):
                if board[i][j]==word[0]:
                    board[i][j]="/"
                    if dfs(i,j,1):
                        return True
                    board[i][j]=word[0]
        return False

30、剑指offer 09

代码实现

class CQueue:

    def __init__(self):
        #负责进的栈
        self.stack1=[]
        #负责出的栈
        self.stack2=[]


    def appendTail(self, value: int) -> None:
        self.stack1.append(value)

    def deleteHead(self) -> int:
        #当stack2为空
        if not self.stack2:
            #stack1也为空
            if not self.stack1:
                return -1
            else:
                while self.stack1:
                    self.stack2.append(self.stack1.pop())
        return self.stack2.pop()


# Your CQueue object will be instantiated and called as such:
# obj = CQueue()
# obj.appendTail(value)
# param_2 = obj.deleteHead()

31、剑指offer 10-i

代码实现

class Solution:
    def fib(self, n: int) -> int:
        if n<=1:
            return n
        dp=[0]*(n+1)
        #初始化dp
        dp[1]=1
        for i in range(2,n+1):
            dp[i]=dp[i-1]+dp[i-2]
        return dp[n]%1000000007

32、剑指offer 03

直接调用了counter就很简单

class Solution:
    def findRepeatNumber(self, nums: List[int]) -> int:
        li=collections.Counter(nums)
        for k,v in li.items():
            if v!=1:
                return k

33、剑指offer 57

参考两数之和

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        i,j=0,len(nums)-1
        while i<j:
            if nums[i]+nums[j]>target:
                j-=1
            elif nums[i]+nums[j]<target:
                i+=1
            else:
                return [nums[i],nums[j]]

34、剑指offer 22

题目描述
在这里插入图片描述

代码实现

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

class Solution:
    def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
        pre,cur=head,head
        for i in range(k):
            cur=cur.next
        while cur:
            cur=cur.next
            pre=pre.next
        return pre

35、剑指offer 21

题目描述
在这里插入图片描述

代码实现
用位运算判断奇偶性

class Solution:
    def exchange(self, nums: List[int]) -> List[int]:
        ji,ou=[],[]
        for x in nums:
            if x&1==1:
                ji.append(x)
            else:
                ou.append(x)
        return ji+ou

36、剑指offer 59-ii

题目描述
在这里插入图片描述

代码实现

import queue
class MaxQueue:

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

    def max_value(self) -> int:
        return self.deque[0] if self.deque else -1


    def push_back(self, value: int) -> None:
        while self.deque and self.deque[-1] < value:
            self.deque.pop()
        self.deque.append(value)
        self.queue.put(value)

    def pop_front(self) -> int:
        if not self.deque:
            return -1
        ans = self.queue.get()
        if ans == self.deque[0]:
            self.deque.popleft()
        return ans

# 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()

37、剑指offer 07

题目描述
在这里插入图片描述

代码实现

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

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        #建立一个中序遍历每个值对应的索引号的字典
        index={k:i for i,k in enumerate(inorder)}
        #构建递归函数
        def dfs(p_l,p_r,in_l,in_r):
            #终止条件
            if p_l>p_r:
                return 
            #定位到根节点
            root_val=preorder[p_l]
            #找到根节点在中序遍历中的位置
            root_idx=index[root_val]
            #建立根节点
            root=TreeNode(root_val)
            #计算左子树的节点数量
            num=root_idx-in_l
            #进入下一层递归
            root.left=dfs(p_l+1,p_l+num,in_l,root_idx-1)
            root.right=dfs(p_l+num+1,p_r,root_idx+1,in_r)
            return root
        n=len(preorder)
        return dfs(0,n-1,0,n-1)

38、剑指offer 20

题目描述
在这里插入图片描述

代码实现

class Solution:
    def isNumber(self, s: str) -> bool:
        states = [
            { ' ': 0, 's': 1, 'd': 2, '.': 4 }, # 0. start with 'blank'
            { 'd': 2, '.': 4 } ,                # 1. 'sign' before 'e'
            { 'd': 2, '.': 3, 'e': 5, ' ': 8 }, # 2. 'digit' before 'dot'
            { 'd': 3, 'e': 5, ' ': 8 },         # 3. 'digit' after 'dot'
            { 'd': 3 },                         # 4. 'digit' after 'dot' (‘blank’ before 'dot')
            { 's': 6, 'd': 7 },                 # 5. 'e'
            { 'd': 7 },                         # 6. 'sign' after 'e'
            { 'd': 7, ' ': 8 },                 # 7. 'digit' after 'e'
            { ' ': 8 }                          # 8. end with 'blank'
        ]
        p = 0                           # start with state 0
        for c in s:
            if '0' <= c <= '9': t = 'd' # digit
            elif c in "+-": t = 's'     # sign
            elif c in "eE": t = 'e'     # e or E
            elif c in ". ": t = c       # dot, blank
            else: t = '?'               # unknown
            if t not in states[p]: return False
            p = states[p][t]
        return p in (2, 3, 7, 8)

39、剑指offer 53-ii

题目描述
在这里插入图片描述

代码实现

class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        n=len(nums)
        total=(n)*(n+1)/2
        return int(total-sum(nums))

二分法

class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        i,j=0,len(nums)-1
        while i<=j:
            m=(i+j)//2
            if nums[m]==m:
                i=m+1
            else:
                j=m-1
        return i

40、剑指offer 59- i

题目描述

在这里插入图片描述

代码实现

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        if not nums:
            return []
        res=[]
        for i in range(0,len(nums)-k+1):
            res.append(max(nums[i:i+k]))
        return res

41、剑指offer 47

题目描述
在这里插入图片描述
代码实现

class Solution:
    def maxValue(self, grid: List[List[int]]) -> int:
        m,n=len(grid),len(grid[0])
        #建立dp
        dp=[[0]*(n+1) for _ in range(m+1)]
        dp[1][1]=grid[0][0]           
        #循环其他位置
        for i in range(1,m+1):
            for j in range(1,n+1):
                if i==1:
                    dp[1][j]=dp[1][j-1]+grid[0][j-1]
                elif j==1:
                    dp[i][1]=dp[i-1][1]+grid[i-1][0]
                #每一个点都可能来自于上面或者左面
                dp[i][j]=max(dp[i-1][j],dp[i][j-1])+grid[i-1][j-1]
        return dp[m][n]

42、剑指offer 64

题目描述
在这里插入图片描述

代码实现

class Solution:
    def sumNums(self, n: int) -> int:
        return n and (n+self.sumNums(n-1))

43、剑指offer 31

题目描述
在这里插入图片描述

代码实现

class Solution:
    def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:
        res=[]
        i=0
        for push in pushed:
            res.append(push)
            while res and res[-1]==popped[i]:
                res.pop()
                i+=1
        return len(res)==0

44、剑指offer 40

题目描述
在这里插入图片描述

代码实现

class Solution:
    def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
        arr.sort()
        return arr[:k]

45、剑指offer 17

题目描述
在这里插入图片描述

代码实现

class Solution:
    def printNumbers(self, n: int) -> List[int]:
        #将n转变为位数
        digit=10**n
        return [num for num in range(1,digit)]

46、剑指offer 28:

题目描述
在这里插入图片描述

代码实现

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

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:
            return True
        def dfs(left,right):
            #当左节点和右节点都没有的时候
            if not left and not right:
                return True
            #当左右节点只有一个
            elif not left or not right:
                return False
            elif left.val!=right.val:
                return False
            else:
                return dfs(left.left,right.right) and dfs(left.right,right.left)
        return dfs(root.left,root.right)

47、剑指offer 19

题目描述
在这里插入图片描述

代码实现

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        #s和p的长度
        m,n=len(s),len(p)
        #定义match函数
        def match(i,j):
            #如果i==0:
            if i==0:
                return False
            #如果是.可以匹配所有
            if p[j-1]==".":
                return True
            return s[i-1]==p[j-1]
        #建立dp
        dp=[[False]*(n+1) for _ in range(m+1)]
        dp[0][0]=True
        #循环
        for i in range(m+1):
            for j in range(1,n+1):
                if p[j-1]=="*":#如果当前是*
                    dp[i][j]|=dp[i][j-2]#可以不匹配*和前一个字符
                    if match(i,j-1):#如果当前s[i-1]==p[j-2]
                        dp[i][j]|=dp[i-1][j]#保留j,匹配i的前一个位置
                else:
                    if match(i,j):
                        dp[i][j]|=dp[i-1][j-1]
        return dp[-1][-1]

48、剑指offer 26

题目描述
在这里插入图片描述

代码实现

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

class Solution:
    def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
        #如果a和b有一个为空
        if not A or not B:
            return False
        def dfs(A,B):
            if not B:
                return True
            if not A or A.val!=B.val:
                return False
            return dfs(A.left,B.left) and dfs(A.right,B.right)
        
        return dfs(A,B) or self.isSubStructure(A.left,B) or self.isSubStructure(A.right,B)

49、剑指offer 66:

题目描述

在这里插入图片描述

代码实现

class Solution:
    def constructArr(self, a: List[int]) -> List[int]:
        b,tmp=[1]*len(a),1
        #计算下三角
        for i in range(1,len(a)):
            b[i]=b[i-1]*a[i-1]
        #计算上三角
        for j in range(len(a)-2,-1,-1):
            tmp*=a[j+1]
            b[j]*=tmp
        return b

50、剑指offer 13:机器人的运动范围

题目描述
在这里插入图片描述

代码实现

def digitsum(n):
    ans=0
    while n:
        ans+=n%10
        n//=10
    return ans
class Solution:
    def movingCount(self, m: int, n: int, k: int) -> int:
        visited=set([(0,0)])
        for i in range(m):
            for j in range(n):
                if ((i-1,j) in visited or (i,j-1) in visited) and (digitsum(i)+digitsum(j)<=k):
                    visited.add((i,j))
        return len(visited)

51、剑指offer 48

题目描述
在这里插入图片描述

代码实现

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        res,temp=0,0
        dic={}
        for j in range(len(s)):
            i=dic.get(s[j],-1)
            #更新
            dic[s[j]]=j
            temp=temp+1 if temp<j-i else j-i
            res=max(res,temp)
        return res

53、剑指offer 06

题目描述

在这里插入图片描述

代码实现

class Solution:
    def replaceSpace(self, s: str) -> str:
        #切片
        li=s.split(" ")
        if not li:
            return ""
        return "%20".join(li)

54、剑指offer 11

题目描述
在这里插入图片描述

代码实现

class Solution:
    def minArray(self, numbers: List[int]) -> int:
        left,right=0,len(numbers)-1
        while left<right:
            mid=(left+right)//2
            if numbers[mid]<numbers[right]:
                right=mid
            elif numbers[mid]>numbers[right]:
                left=mid+1
            else:
                right-=1
        return numbers[left]

55、剑指offer 56-i

题目描述
在这里插入图片描述

代码实现

class Solution:
    def singleNumbers(self, nums: List[int]) -> List[int]:
        x,y,m,n=0,0,1,0
        for num in nums:
            n^=num
        while n&m==0:
            m<<=1
        for num in nums:
            if num&m:
                x^=num
            else:
                y^=num
        return [x,y]

56、剑指offer 56-ii

题目描述
在这里插入图片描述

代码实现

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        dic=collections.defaultdict(int)
        for num in nums:
            dic[num]+=1
        for k,v in dic.items():
            if v==1:
                return k

57、剑指offer 39

题目描述
在这里插入图片描述

代码实现

class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        vote=0
        for num in nums:
            if vote==0:
                x=num
            vote+=1 if num==x else -1
        return x

58、剑指offer 57-ii

题目描述

在这里插入图片描述

代码实现

class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        #定义左右指针
        i,j,s=1,2,3
        res=[]
        while i<j:
            if s==target:
                res.append(list(range(i,j+1)))
            if s>=target:
                s-=i
                i+=1
            if s<target:
                j+=1
                s+=j
        return res

59、剑指offer 62

题目描述
在这里插入图片描述

代码实现

class Solution:
    def lastRemaining(self, n: int, m: int) -> int:
        x=0
        for i in range(2,n+1):
            x=(x+m)%i
        return x

60、剑指offer 58

题目描述
在这里插入图片描述

代码实现

class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        return s[n:]+s[:n]

61、剑指offer 35

题目描述
在这里插入图片描述

代码实现

"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""
class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        if not head:
            return 
        dic={}
        cur=head
        while cur:
            dic[cur]=Node(cur.val)
            cur=cur.next
        cur=head
        while cur:
            dic[cur].next=dic.get(cur.next)
            dic[cur].random=dic.get(cur.random)
            cur=cur.next
        return dic[head]

62、剑指offer 55-ii

题目描述

在这里插入图片描述

解题思路

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

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        def dfs(root):
            if not root:
                return 0
            left=dfs(root.left)
            if left == -1:
                return -1
            right=dfs(root.right)
            if right==-1:
                return -1
            return max(left,right)+1 if abs(left-right)<=1 else -1
        return dfs(root)!=-1

63、剑指offer 61

题目描述
在这里插入图片描述

代码实现

class Solution:
    def isStraight(self, nums: List[int]) -> bool:
        repeat=set()
        ma,mi=0,14
        for nums in nums:
            if nums==0:
                continue
            ma=max(ma,nums)
            mi=min(mi,nums)
            if nums in repeat:
                return False
            repeat.add(nums)
        return ma-mi<5

64、剑指offer 16

题目描述

在这里插入图片描述

代码实现

class Solution:
    def myPow(self, x: float, n: int) -> float:
        def split(N):
            if N==0:
                return 1.0
            y=split(N//2)
            return y*y if N%2==0 else y*y*x
        return split(n) if n>0 else 1.0/split(-n)
class Solution:
    def myPow(self, x: float, n: int) -> float:
        if n==0:
            return 1
        if n<0:
            x=1/x
            n=-n
        res=1
        while n:
            if n&1:
                res*=x
            x*=x
            n>>=1
        return res

65、剑指offer 37

题目描述
在这里插入图片描述

代码实现

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

class Codec:

    def serialize(self, root):
        """Encodes a tree to a single string.
        
        :type root: TreeNode
        :rtype: str
        """
        if not root:
            return ""
        res=[]
        queue=collections.deque([root])
        while queue:
            node=queue.popleft()
            if node:
                res.append(str(node.val))
                queue.append(node.left)
                queue.append(node.right)
            else:
                res.append("None")
        return "["+",".join(res)+"]"
        

    def deserialize(self, data):
        """Decodes your encoded data to tree.
        
        :type data: str
        :rtype: TreeNode
        """
        if not data:
            return []
        #拆分
        datalist=data[1:-1].split(",")
        root=TreeNode(int(datalist[0]))
        i=1
        queue=collections.deque([root])
        while queue:
            node=queue.popleft()
            if datalist[i]!="None":
                node.left=TreeNode(int(datalist[i]))
                queue.append(node.left)
            i+=1
            if datalist[i]!="None":
                node.right=TreeNode(int(datalist[i]))
                queue.append(node.right)
            i+=1
        return root
        

# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.deserialize(codec.serialize(root))

66、剑指offer 44

题目描述
在这里插入图片描述

代码实现

class Solution:
    def findNthDigit(self, n: int) -> int:
        digit,start,count=1,1,9
        while n>count:
            n-=count
            digit+=1
            start*=10
            count=9*digit*start
        num=start+(n-1)//digit
        return int(str(num)[(n-1)%digit])

67、剑指offer 67

题目描述
在这里插入图片描述

代码实现

class Solution:
    def strToInt(self, str: str) -> int:
        #切片
        slices=list(str.strip())
        if len(slices)==0:
            return 0
        #查看符号
        signal = -1 if slices[0]=="-" else 1
        #删除符号
        if slices[0] in ["+","-"]:
            del slices[0]
        res,i=0,0
        #遍历
        while i<len(slices) and slices[i].isdigit():
            res=10*res+ord(slices[i])-ord("0")
            i+=1
        return min(2**31-1,max(-2**31,res*signal))

68、剑指offer 45

题目描述
在这里插入图片描述

代码实现

class Solution:
    def minNumber(self, nums: List[int]) -> str:
        strs=[str(num) for num in nums]
        def quicksort(l,r):
            if l>=r:
                return 
            i,j=l,r
            while i<j:
                while strs[j]+strs[l]>=strs[l]+strs[j] and i<j:
                    j-=1
                while strs[i]+strs[l]<=strs[l]+strs[i] and i<j:
                    i+=1
                strs[i],strs[j]=strs[j],strs[i]
            strs[i],strs[l]=strs[l],strs[i]
            quicksort(l,i-1)
            quicksort(i+1,r)
        quicksort(0,len(strs)-1)
        return "".join(strs)

2、Leetcode

1、Leetcode 192:统计词频

题目描述

代码实现

python3 -c "a=open('words.txt').read().split();from collections import Counter;c=list(Counter(a).items());c.sort(key=lambda x:-x[1]);[print(x,y)for x,y in c]"

2、Leetcode 916:单词子集

题目描述
在这里插入图片描述

解题思路
核心思路有两个

  • 1、如果A中的小a要满足输出条件,那么小a的26个字母出现的频次(简称频次)要大于B中的每个小b的频次的并集。
  • 2、对于B中的小b的频次的并集,每个字母的频次只取每个小b最大的频次,例如[“bba”,“b”],对于b这个字母的频次只取两次。
  • 3、使用一个长度为26的列表储存每个单词的频次。

代码实现

class Solution:
    def wordSubsets(self, A: List[str], B: List[str]) -> List[str]:
        #统计B中每个letter的频次
        def count(word):
            freq=[0]*26
            for letter in word:
                freq[ord(letter)-ord("a")]+=1
            return freq
        #对于B的频次统计,取每个字母最大的频次
        save=[0]*26
        for b in B:
            for i,c in enumerate(count(b)):
                save[i]=max(save[i],c)
        res=[]
        #再判断A中每个单词的频次是否全部大于b
        for a in A:
            if all(x>=y for x,y in zip(count(a),save)):
                res.append(a)
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Offer》 1. 赋值运算函数 2. 单例设计模式 3. 二维数组中查找目标值 4. 替换字符串中的空格 5. 从尾到头打印链表 6. 由前序和中序遍历重建二叉树 7. 用两个栈实现队列 8. 求旋转数组的最小数字 9. 斐波那契数列的第n项(青蛙跳台阶) 10. 二进制中1的个数 11. 数值的整数次方 12. 打印1到最大的n位数 13. O(1)时间删除链表节点 14. 使数组中的奇数位于偶数前面 15. 找链表中倒数第K个节点 16. 输出反转后的链表 17. 合并两个有序链表 18. 判断二叉树A中是否包含子树B 19. 二叉树的镜像 20. 顺时针打印矩阵 21. 包含min函数的栈 22. 判断一个栈是否是另一个栈的弹出序列 23. 层序遍历二叉树 24. 后序遍历二叉搜索树 25. 二叉树中和为某值的路径 26. 复杂链表的复制 27. 二叉搜索树转换为双向链表 28. 打印字符串中所有字符的排列 29. 数组中出现次数超过一半的数字 30. 找出最小的K个数 31. 连续子数组的最大和 32. 从1到整数n中1出现的次数 33. 把数组中的数排成一个最小的数 34. 求第N个丑数 35. 第一个出现一次的字符 36. 数组中逆序对的个数 37. 两个链表的第一个公共节点 38. 数字在排序数组中出现的次数 39. 二叉树的深度 40. 数组中只出现一次的两个数,而其他数都出现两次 41. 和为s的连续整数序列 42. 翻转字符串 43. n个骰子的点数及出现的概率 44. 扑克牌的顺子 45. 圆圈中最后剩下的数 46. 1+2+3+...+n的和 47. 不用加减乘除做加法 48. 不能被继承的类 49. 字符串转换为整数 50. 树中两个节点的最低公共祖先 51. 找出重复的数 52. 构建乘积数组 53. 正则表达式匹配 54. 表示数值的字符串 55. 字符流中第一个不重复的字符 56. 链表中环的入口节点 57. 删除链表中重复的节点 58. 二叉树的下一个节点 59. 对称的二叉树 60. 按之字形顺序打印二叉树 61. 把二叉树打印成多行 62. 序列化二叉树 63. 二叉搜索树的第K个节点 64. 数据流中的中位数 65. 滑动窗口的最大值 66. 矩阵中的路径 67. 机器人的运动范围
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值