目录
- 剑指offer系列
- 1、剑指Offer 25
- 2、剑指offer 24
- 3、剑指offer 06
- 4、剑指offer 15
- 5、剑指offer 27
- 6、剑指offer 32-i
- 7、剑指offer32-ii
- 8、剑指offer 32- iii
- 9、面试题30
- 10、剑指offer 18
- 11、剑指offer 04
- 12、剑指offer 55- i
- 13、剑指offer 65
- 14、剑指offer 52
- 15、剑指offer 68-ii
- 16、剑指offer 49
- 17、剑指offer 14-i
- 18、剑指offer 14-ii
- 19、面试题 34
- 20、剑指offer 54
- 21、剑指offer 68-i
- 22、剑指offer 33
- 23、剑指offer 36
- 24、剑指offer 60
- 25、剑指offer 43
- 26、剑指offer 42
- 27、剑指offer 63
- 28、剑指offer 58-i
- 29、剑指offer 12
- 30、剑指offer 09
- 31、剑指offer 10-i
- 32、剑指offer 03
- 33、剑指offer 57
- 34、剑指offer 22
- 35、剑指offer 21
- 36、剑指offer 59-ii
- 37、剑指offer 07
- 38、剑指offer 20
- 39、剑指offer 53-ii
- 40、剑指offer 59- i
- 41、剑指offer 47
- 42、剑指offer 64
- 43、剑指offer 31
- 44、剑指offer 40
- 45、剑指offer 17
- 46、剑指offer 28:
- 47、剑指offer 19
- 48、剑指offer 26
- 49、剑指offer 66:
- 50、剑指offer 13:机器人的运动范围
- 51、剑指offer 48
- 53、剑指offer 06
- 54、剑指offer 11
- 55、剑指offer 56-i
- 56、剑指offer 56-ii
- 57、剑指offer 39
- 58、剑指offer 57-ii
- 59、剑指offer 62
- 60、剑指offer 58
- 61、剑指offer 35
- 62、剑指offer 55-ii
- 63、剑指offer 61
- 64、剑指offer 16
- 65、剑指offer 37
- 66、剑指offer 44
- 67、剑指offer 67
- 68、剑指offer 45
- 2、Leetcode
剑指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