class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: bool
"""
# 顺序查找最小的数为数组nums有序的分界点
def findMin(nums):
i, n = 0, len(nums)
for j in range(1, n):
if nums[j] >= nums[i]:
i += 1
else:
return j # 如果nums[j]小于nums[i],返回j。当最小的数有数个,返回最左边的那个
return 0 # 列表有序,最小的数在第0位
# 二分查找
def binary(nums, target):
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r)//2
if nums[mid] == target:
return True
elif nums[mid] > target:
r = mid - 1
else:
l = mid + 1
return False
l, r = 0, len(nums)-1
mini = findMin(nums)
if not nums or target < nums[mini]:
return False
if mini == l: # # mini在第一位,直接使用二分查找
return binary(nums, target)
if target >= nums[l]:
return binary(nums[0:mini], target)
else:
return binary(nums[mini:], target)
思路
O(∩_∩)O哈哈~
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: bool
"""
return True if target in nums else False
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head or head.next == None:
return head
l, r = head, head.next
rehead = ListNode(None)
cur = rehead
while r != None:
if l.val != r.val:
if l.next == r:
cur.next = ListNode(l.val)
cur = cur.next
l = r
r = r.next
if l.next == None:
cur.next = ListNode(l.val)
return rehead.next
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head or head.next == None:
return head
l, r = head, head.next
while r != None:
if l.val != r.val:
l = l.next
l.val = r.val
r = r.next
l.next = None
return head
class Solution(object):
def largestRectangleArea(self, heights):
"""
:type heights: List[int]
:rtype: int
"""
n = len(heights)
if not n:
return 0
stack, max_area = list(), 0
stack.append(-1)
for i in range(n):
while stack[-1] != -1 and heights[stack[-1]] >= heights[i]:
max_area = max(max_area, heights[stack.pop()]*(i-stack[-1]-1))
stack.append(i)
while stack[-1] != -1:
max_area = max(max_area, heights[stack.pop()]*(n-stack[-1]-1))
return max_area
思路
遍历每一行求84. 柱状图中最大的矩形
栗子:
matrix = [
[“1”,“0”,“1”,“0”,“0”],
[“1”,“0”,“1”,“1”,“1”],
[“1”,“1”,“1”,“1”,“1”],
[“1”,“0”,“0”,“1”,“0”]
]
第一行的柱状图heights: [1, 0, 1, 0, 0]
第二行的柱状图heights: [2, 0, 2, 1, 1]
第三行的柱状图heights: [3, 1, 3, 2, 2]
第四行的柱状图heights: [4, 0, 0, 3, 0]
class Solution(object):
def maximalRectangle(self, matrix):
"""
:type matrix: List[List[str]]
:rtype: int
"""
if not matrix:
return 0
def largestRectangleArea(heights):
stack, max_area = list(), 0
stack.append(-1)
for i in range(n):
while stack[-1] != -1 and heights[stack[-1]] >= heights[i]:
max_area = max(max_area, heights[stack.pop()]*(i-stack[-1]-1))
stack.append(i)
while stack[-1] != -1:
max_area = max(max_area, heights[stack.pop()]*(n-stack[-1]-1))
return max_area
m, n, max_area = len(matrix), len(matrix[0]), 0
heights = [0]*n
for i in range(m):
for j in range(n):
heights[j] =heights[j] + 1 if matrix[i][j]=='1' else 0
# print(heights)
max_area = max(max_area, largestRectangleArea(heights))
return max_area
head -> 1 -> 4 -> 3 -> 2 -> 5 -> 2
x = 3
##############################
r,rehead
0 -> 1 -> 4 -> 3 -> 2 -> 5 -> 2
r,l
0 -> 1 -> 4 -> 3 -> 2 -> 5 -> 2
l r t
0 -> 1 -> 4 -> 3 -> 2 -> 5 -> 2
l t r
0 -> 1 -> 2 -> 4 -> 3 -> 5 -> 2
l r
0 -> 1 -> 2 -> 4 -> 3 -> 5 -> 2
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def partition(self, head, x):
"""
:type head: ListNode
:type x: int
:rtype: ListNode
"""
if not head or head.next == None:
return head
r = ListNode(0)
r.next = head
rehead = r
while r.next != None and r.next.val < x: # 当结点小于x时,r往右走直到r.next.val大于x,作为第一个可插入的位置
r = r.next
l = r # l 指向 r,记录插入位置的前置结点
while r.next != None:
while r.next != None and r.next.val >= x: # 当r.next.val大于等于x时,往右走寻找小于x的结点
r = r.next
if r.next !=None:
t = r.next # t保存小于x的结点
r.next = r.next.next # r指向t后面的结点,将t结点提取出来
t.next = l.next # t结点指向l的下一个结点
l.next = t # l结点连接t结点
l = l.next # 更新l
return rehead.next
class Solution(object):
def isScramble(self, s1, s2):
"""
:type s1: str
:type s2: str
:rtype: bool
"""
n1, n2 = len(s1), len(s2)
if n1 != n2: # 字符串长度不相等
return False
if sorted(s1) != sorted(s2): # 字符串的字符不相等
return False
if s1 == s2: # 字符串相等
return True
for i in range(1, n1):
if (self.isScramble(s1[:i], s2[:i]) and self.isScramble(s1[i:], s2[i:])) or \
(self.isScramble(s1[:i], s2[-i:]) and self.isScramble(s1[i:], s2[:-i])):
return True
return False
思路
sort(): 对list排序会修改list本身,不会返回新list
sorted(): 返回的排序后的 list
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: None Do not return anything, modify nums1 in-place instead.
"""
nums1[:] = sorted(nums1[:m] + nums2[:n])
return nums1
格雷码-百度百科
递归生成码表
这种方法基于格雷码是反射码的事实,利用递归的如下规则来构造:
- 1位格雷码有两个码字
- (n+1)位格雷码中的前2n个码字等于n位格雷码的码字,按顺序书写,加前缀0
- (n+1)位格雷码中的后2n个码字等于n位格雷码的码字,按逆序书写,加前缀1
- n+1位格雷码的集合 = n位格雷码集合(顺序)加前缀0 + n位格雷码集合(逆序)加前缀1
1位格雷码 | 2位格雷码 | 3位格雷码 |
---|---|---|
0 | 00 | 000 |
1 | 01 | 001 |
- | 11 | 011 |
- | 10 | 010 |
- | - | 110 |
- | - | 111 |
- | - | 101 |
- | - | 100 |
class Solution(object):
def grayCode(self, n):
"""
:type n: int
:rtype: List[int]
"""
def gray(n):
if n == 0:
return ["0"]
if n == 1:
return ["0", "1"]
ans = list()
for num in gray(n-1):
ans.append("0"+num)
for num in reversed(gray(n-1)):
ans.append("1"+num)
return ans
return list(map(lambda num:int(num, 2), gray(n)))
class Solution(object):
def subsetsWithDup(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums.sort()
ans = [[]]
for num in nums:
ans += [pre+[num] for pre in ans if pre+[num] not in ans]
return ans
class Solution(object):
def numDecodings(self, s):
"""
:type s: str
:rtype: int
"""
if not s or s[0]=="0": # s为空或第一个字符为0,返回0
return 0
n = len(s)
dp = [None]*n # 创建dp数组
dp[0] = 1 # 初始化dp数组第一个数为1
for i in range(1, n):
if s[i] == "0":
if s[i-1] == "1" or s[i-1] == "2":
dp[i] = dp[i-2] if i > 1 else dp[i-1]
else:
return 0
elif (s[i-1] == "1" and int(s[i])<=9) or (s[i-1] == "2" and int(s[i]) <= 6):
dp[i] = dp[i-1] + dp[i-2] if i > 1 else dp[i-1]+1
else:
dp[i] = dp[i-1]
return dp[-1]
head -> 1 -> 2 -> 3 -> 4 -> 5
m, n = 2, 4
##############################
p,pre,tail
-1 -> 1 -> 2 -> 3 -> 4 -> 5
p pre tail
-1 -> 1 -> 2 -> 3 -> 4 -> 5
p pre tail cur
-1 -> 1 -> 3 -> 4 -> 2 -> 5
p pre tail cur
-1 -> 1 -> 4 -> 3 -> 2 -> 5
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseBetween(self, head, m, n):
"""
:type head: ListNode
:type m: int
:type n: int
:rtype: ListNode
"""
p = ListNode(-1)
p.next = head
pre, tail = p, p
tmp = list
while m-1 > 0: # 寻找第m-1结点作为前置结点pre
pre = pre.next
m -= 1
while n > 0: # 寻找第n个结点作为tail
tail = tail.next
n -= 1
while pre.next != tail: # 寻找第n个结点作为tail
cur = pre.next
pre.next = cur.next
cur.next = tail.next
tail.next = cur
return p.next
class Solution(object):
def restoreIpAddresses(self, s):
"""
:type s: str
:rtype: List[str]
"""
def backtrack(s, tmp=list()):
if len(tmp) == 4: # 当tmp长度等于4,s字符串没有字符时,添加tmp至ans
if not s:
ans.append(".".join(tmp))
return
for cur in range(1, min(4, len(s)+1)): # 因为列表s[:cur]的区间是[),所以cur取值最大为len(s)
if int(s[:cur])<0 or int(s[:cur]) > 255 or (cur > 1 and s[0]=="0"):
break
backtrack(s[cur:],tmp+[s[:cur]])
ans = list()
backtrack(s)
return ans
递归
# 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 inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
def helper(root, ans=list()):
if root == None:
return []
helper(root.left)
ans.append(root.val)
helper(root.right)
return ans
return helper(root)
def inorder(root):
return [] if root == None else inorder(root.left) + [root.val] + inorder(root.right)
思路
栈实现
class Solution(object):
def inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
stack, ans = list(), list()
while root or stack:
while root != None:
stack.append(root)
root = root.left
root = stack.pop()
ans.append(root.val)
root = root.right
return ans
思路
递归:
从1到n的数作为根结点,left(start, i-1)递归构建左子树,(i+1, end)递归构建右子树
# 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 generateTrees(self, n):
"""
:type n: int
:rtype: List[TreeNode]
"""
def __generateTrees(start, end):
if start > end:
return [None]
ans = list()
for i in range(start, end+1):
left = __generateTrees(start, i-1)
right = __generateTrees(i+1, end)
for l in left:
for r in right:
root = TreeNode(i)
root.left = l
root.right = r
ans.append(root)
return ans
return __generateTrees(1, n) if n else []
卡特兰数_百度百科
卡特兰数 C n C_n Cn满足以下递推关系:
- C n + 1 = C 0 C n + C 1 C n − 1 + ⋯ + C n C 0 C_n+1 = C_0C_n + C_1C_{n-1} + \cdots + C_nC0 Cn+1=C0Cn+C1Cn−1+⋯+CnC0
- ( n − 3 ) C n = n 2 ( C 3 C n − 1 + C 4 C n − 2 + C 5 C n − 3 + C n − 2 C 4 + C n − 1 C 4 ) (n - 3)C_n = \frac{n}{2}(C_3C_{n-1} + C_4C_{n-2} + C_5C_{n-3} + C_{n-2}C_4 + C_{n-1}C_4) (n−3)Cn=2n(C3Cn−1+C4Cn−2+C5Cn−3+Cn−2C4+Cn−1C4)
设 h ( n ) h(n) h(n)为catalan数的第 n + 1 n+1 n+1项,令 h ( 0 ) = 1 , h ( 1 ) = 1 h(0)=1,h(1)=1 h(0)=1,h(1)=1,catalan数满足递推式:
h ( n ) = h ( 0 ) × h ( n − 1 ) + h ( 1 ) × h ( n − 2 ) + . . . + h ( n − 1 ) × h ( 0 ) ( n > = 2 ) h(n)= h(0)\times h(n-1)+h(1)\times h(n-2) + ... + h(n-1)\times h(0) (n>=2) h(n)=h(0)×h(n−1)+h(1)×h(n−2)+...+h(n−1)×h(0)(n>=2)
另类递推式:
h ( n ) = h ( n − 1 ) × ( 4 × n − 2 ) / ( n + 1 ) h(n)=h(n-1)\times(4\times n-2)/(n+1) h(n)=h(n−1)×(4×n−2)/(n+1)给定节点组成二叉搜索树
给定 n n n个节点,能构成多少种不同的二叉搜索树?
能构成 h ( n ) h(n) h(n)个,这个公式的下标是从 h ( 0 ) h(0) h(0)=1开始
class Solution(object):
def numTrees(self, n):
"""
:type n: int
:rtype: int
"""
if n == 0:
return 1
if n == 1:
return 1
return self.numTrees(n-1)*(4*n-2)//(n+1)
class Solution(object):
def isInterleave(self, s1, s2, s3):
"""
:type s1: str
:type s2: str
:type s3: str
:rtype: bool
"""
n1, n2, n3 = len(s1), len(s2), len(s3)
if n1 + n2 != n3:
return False
dp = [[None]*(n2+1) for _ in range(n1+1)]
dp[0][0] = True
for i in range(1, n1+1):
dp[i][0] = dp[i-1][0] and s1[i-1] == s3[i-1]
for i in range(1, n2+1):
dp[0][i] = dp[0][i-1] and s2[i-1] == s3[i-1]
for i in range(1, n1+1):
for j in range(1, n2+1):
dp[i][j] = (dp[i-1][j] and s1[i-1] == s3[i-1+j]) or (dp[i][j-1] and s2[j-1] == s3[j-1+i])
return dp[-1][-1]
# 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 isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
def helper(root, left, right):
if root == None:
return True
val = root.val
if val <= left or val >= right:
return False
if not helper(root.left, left, val):
return False
if not helper(root.right, val, right):
return False
return True
return helper(root, float("-inf"), float("inf"))
一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数
节点的右子树只包含大于当前节点的数
所有左子树和右子树自身必须也是二叉搜索树
中序遍历:左根右
先遍历到的结点pre比后遍历到的结点root大,找到错误交换的结点x,y
class Solution(object):
def recoverTree(self, root):
"""
:type root: TreeNode
:rtype: None Do not return anything, modify root in-place instead.
"""
x, y, pre = None, None, None
stack = list()
while root or stack:
while root != None:
stack.append(root)
root = root.left
root = stack.pop()
if pre and pre.val > root.val: # 先遍历到的结点比后遍历到的结点大,找到错误交换的结点
y = root
if x == None:
x = pre
else:
break
pre = root
root = root.right
x.val, y.val = y.val, x.val
class Solution(object):
def isSameTree(self, p, q):
"""
:type p: TreeNode
:type q: TreeNode
:rtype: bool
"""
if p == None and q == None:
return True
if p == None or q == None:
return False
if p.val != q.val:
return False
return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)