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
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 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
注意快排练习,又写错了
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)
注意下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]
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
这题我想不清楚
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])
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))))
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]
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]
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
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]
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
归并排序
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
# 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
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
中序遍历
# 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
# 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
从根结点开始递归,防止反复计算
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
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
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])
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)
单调队列
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
同上
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()
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
用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
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
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
class Solution(object):
def sumNums(self, n):
"""
:type n: int
:rtype: int
"""
if n == 1:
return 1
return n+self.sumNums(n-1)
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
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
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