版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明,违反必究。
本文链接:https://blog.youkuaiyun.com/junxing2018_wu/article/details/117440975
二叉树遍历
# -*- coding: utf-8 -*-
from typing import List
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
# 根 左 右
if root is None:
return []
result = [root.val]
stack = [root.right, root.left]
while len(stack) > 0:
node = stack.pop()
if node is not None:
result.append(node.val)
stack.extend([node.right, node.left])
return result
def postorderTraversal(self, root: TreeNode) -> List[int]:
# 左 右 根
# = [根 右 左][::-1]
if root is None:
return []
result = [root.val]
stack = [root.left, root.right]
while len(stack) > 0:
node = stack.pop()
if node is not None:
result.append(node.val)
stack.extend([node.left, node.right])
return result[::-1]
def inorderTraversal(self, root: TreeNode) -> List[int]:
# 左 根 右
if root is None:
return []
node = root
result = []
stack = []
while stack or node:
while node:
stack.append(node)
node = node.left
if stack:
node = stack.pop()
result.append(node.val)
node = node.right
return result
def levelOrder(self, root: TreeNode) -> List[List[int]]:
def children(root: TreeNode):
return [n for n in [root.left, root.right] if n is not None]
if root is None:
return []
else:
result = []
node_list = [root]
while len(node_list) > 0:
result.append([n.val for n in node_list])
tmp_stack = []
for n in node_list:
tmp_stack += children(n)
node_list = tmp_stack
return result
if __name__ == "__main__":
a = TreeNode("a")
b = TreeNode("b")
c = TreeNode("c")
d = TreeNode("d")
e = TreeNode("e")
f = TreeNode("f")
g = TreeNode("g")
a.left = b
a.right = c
b.left = d
b.right = e
c.left = f
c.right = g
s = Solution()
print(s.postorderTraversal(a))
print(s.preorderTraversal(a))
print(s.inorderTraversal(a))
数组排序
# -*- coding: utf-8 -*-
import copy, random
from typing import List
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
# return self.bubblesort(nums)
# return self.selectsort(nums)
# return self.insertionsort(nums)
# return self.shellsort(nums)
# return self.quicksort(nums, 0, len(nums)-1)
# return self.mergesort(nums)
return self.heapsort(nums)
def swapnum(self, nums: List[int], i: int, j: int) -> List[int]:
nums[i], nums[j] = nums[j], nums[i]
def bubblesort(self, nums: List[int]) -> List[int]:
l = len(nums)
for i in range(l):
for j in range(1, l):
if nums[j - 1] > nums[j]:
self.swapnum(nums, j - 1, j)
return nums
def selectsort(self, nums: List[int]) -> List[int]:
l = len(nums)
if l <= 1:
return nums
for i in range(l - 1):
# index_min_num:i
for j in range(i, l):
if nums[j] < nums[i]:
self.swapnum(nums, i, j)
return nums
def insertionsort(self, nums: List[int]) -> List[int]:
l = len(nums)
for i in range(1, l):
need_insert_num = nums[i]
# 将nums[i]插入已排序序列nums[1..j-1]
j = i - 1
while j >= 0 and nums[j] > need_insert_num:
nums[j + 1] = nums[j]
j -= 1
nums[j + 1] = need_insert_num
return nums
# 希尔排序
def shellsort(self, nums: List[int]) -> List[int]:
l = len(nums)
gap = 1
gapc = 3
while gap < l / gapc:
gap = gap * gapc + 1
while gap > 0:
# 下边就是一个插入排序
for i in range(gap, l):
temp = nums[i]
j = i - gap
while j >= 0 and nums[j] > temp:
nums[j + gap] = nums[j]
j -= gap
nums[j + gap] = temp
gap = gap // gapc
return nums
def mergesort(self, nums: List[int]) -> List[int]:
def mergenums(left: list, right: list):
result = []
while left and right:
if left[0] <= right[0]:
result.append(left.pop(0))
else:
result.append(right.pop(0))
result += left + right
return result
l = len(nums)
if l < 2:
return nums
middle_index = l >> 1
return mergenums(
self.mergesort(nums[:middle_index]), self.mergesort(nums[middle_index:])
)
def quicksort(self, nums: List[int], left: int, right: int) -> List[int]:
def partition(nums, left, right):
index = left + 1
for i in range(index, right + 1):
if nums[i] < nums[left]:
self.swapnum(nums, i, index)
index += 1
self.swapnum(nums, left, index - 1)
return index - 1
if left < right:
partitionindex = partition(nums, left, right)
self.quicksort(nums, left, partitionindex - 1)
self.quicksort(nums, partitionindex + 1, right)
return nums
def heapsort(self, nums):
"""
堆排序
"""
def build_maxheap(nums):
"""
创建大根堆
"""
for i in range(len(nums) // 2, -1, -1):
# 从最外层开始构建大根堆
max_heapify(nums, i, len(nums))
def max_heapify(nums, i, size):
"""
最大化堆,i 为 堆头id
"""
left = 2 * i + 1
right = 2 * i + 2
largest = i
if left < size and nums[left] > nums[largest]:
largest = left
if right < size and nums[right] > nums[largest]:
largest = right
if largest != i:
self.swapnum(nums, i, largest)
max_heapify(nums, largest, size)
l = len(nums)
# 建堆,将初始序列建成一个大根堆
build_maxheap(nums)
for i in range(l - 1, 0, -1):
# 将根节点(首元素)与最后一个元素交换
self.swapnum(nums, 0, i)
# 堆有序化, 让当前跟节点(首元素)值最大
# 最后一个元素是最大的不参与后续排序了
max_heapify(nums, 0, i)
return nums
s = Solution()
nums = [2, 3, 5, 7, 9, 6, 4, 8, 1, 0]
for i in range(10):
n = copy.deepcopy(nums)
random.shuffle(n)
print(s.bubblesort(n))
print(s.selectsort(n))
print(s.insertionsort(n))
print(s.shellsort(n))
print(s.quicksort(n, 0, len(nums) - 1))
print(s.mergesort(n))
print(s.heapsort(n))
求最长公共子序列
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
m, n = len(text1), len(text2)
dp = [[0] * (n + 1) for i in range(m + 1)]
record = [[""] * (n + 1) for i in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if text1[i - 1] == text2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
record[i][j] = record[i - 1][j - 1] + text1[i - 1]
else:
# dp[i][j] = max(dp[i][j-1], dp[i-1][j])
if dp[i][j - 1] > dp[i - 1][j]:
dp[i][j] = dp[i][j - 1]
record[i][j] = record[i][j - 1]
else:
dp[i][j] = dp[i - 1][j]
record[i][j] = record[i - 1][j]
print(record)
print(dp)
return dp[m][n]
if __name__ == "__main__":
s = Solution()
print(s.longestCommonSubsequence("asfdgfagfa", "daekcsagea"))
# asaga
列举所有全排列
# -*- coding: utf-8 -*-
from typing import List
class Solution:
# 通过回溯法——深度优先搜索(dfs)递归
def permute(self, nums: List[int]) -> List[List[int]]:
ret = []
path = []
def dfs(li):
if len(li) == len(path):
ret.append(path[:])
return
for i in li:
if i not in path:
path.append(i)
dfs(li)
path.pop()
dfs(nums)
return ret
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
ret = []
path = []
def dfs(lst, used):
if len(lst) == len(path):
ret.append(path[:])
return
for i in range(len(lst)):
if used[i]:
continue
if i > 0 and lst[i] == lst[i - 1] and not used[i - 1]:
continue
used[i] = True
path.append(lst[i])
dfs(lst, used)
used[i] = False
path.pop()
nums.sort()
dfs(nums, [False] * len(nums))
return ret
判断链表中是否有环
# -*- coding: utf-8 -*-
from typing import List
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 龟兔赛跑,快慢指针
def hasCycle(self, head: ListNode) -> bool:
if not head or not head.next:
return False
slow = head
fast = head.next
while slow != fast:
if not fast or not fast.next:
return False
slow = slow.next
fast = fast.next.next
return True
求最短路径
给定
N
×
N
N \times N
N×N的矩阵
A
A
A,其中
A
[
i
]
[
j
]
A[i][j]
A[i][j]表示相邻节点到达该点的距离。
每一步,都可以在上、下、左、右移动。
计算从[0,0] 到 [N-1, N-1] 最短路径。
即 求一条路径
[
0
,
0
]
−
>
.
.
.
−
>
[
N
−
1
,
N
−
1
]
[0,0] -> ... ->[N-1, N-1]
[0,0]−>...−>[N−1,N−1],使得
A
[
0
]
[
0
]
+
.
.
.
+
A
[
N
−
1
]
[
N
−
1
]
A[0][0] + ...+ A[N-1][N-1]
A[0][0]+...+A[N−1][N−1]最小。
def update(dist, i, j, a, b, c, d):
# 更新dist
if i > 0 and float("inf") != a and dist[i - 1][j] > a:
dist[i - 1][j] = a
if j > 0 and float("inf") != b and dist[i][j - 1] > b:
dist[i][j - 1] = b
if i < len(dist) - 1 and float("inf") != c and dist[i + 1][j] > c:
dist[i + 1][j] = c
if j < len(dist) - 1 and float("inf") != d and dist[i][j + 1] > d:
dist[i][j + 1] = d
return dist
def dijkstra(nums):
length = len(nums)
dist = [[float("inf")] * length for _ in range(length)]
dist[0][0] = nums[0][0]
done = [(0, 0)]
i, j = 0, 0
while i < length and j < length and dist[length - 1][length - 1] == float("inf"):
a, b, c, d = float("inf"), float("inf"), float("inf"), float("inf")
if i > 0:
a = dist[i][j] + nums[i - 1][j]
if j > 0:
b = dist[i][j] + nums[i][j - 1]
if i < length - 1:
c = dist[i][j] + nums[i + 1][j]
if j < length - 1:
d = dist[i][j] + nums[i][j + 1]
# 节点跳转
if a < min(b, c, d) and (i - 1, j) not in done:
dist[i - 1][j] = min(a, dist[i - 1][j])
dist = update(dist, i, j, a, b, c, d)
i -= 1
elif b < min(c, d) and (i, j - 1) not in done:
dist[i][j - 1] = min(b, dist[i][j - 1])
dist = update(dist, i, j, a, b, c, d)
j -= 1
elif c < d and i < length - 1 and (i + 1, j) not in done:
dist[i + 1][j] = min(c, dist[i + 1][j])
dist = update(dist, i, j, a, b, c, d)
i += 1
elif j < length - 1 and (i, j + 1) not in done:
dist[i][j + 1] = min(d, dist[i][j + 1])
dist = update(dist, i, j, a, b, c, d)
j += 1
else:
print("程序有问题,请检查!")
break
done.append((i, j))
print(f"i: {i}, j: {j}")
print(f"a: {a}, b: {b}, c: {c}, d: {d}")
print(done)
print(dist)
# import pdb; pdb.set_trace();
return i, j, dist[length - 1][length - 1]
print(
dijkstra(
[
[1, 2, 32, 31, 30, 29, 28, 27],
[33, 3, 4, 26, 25, 24, 23, 22],
[34, 35, 5, 6, 7, 19, 20, 21],
[36, 37, 38, 39, 8, 18, 16, 17],
[43, 42, 41, 40, 9, 10, 15, 14],
[44, 45, 46, 47, 48, 11, 49, 50],
[51, 52, 53, 54, 55, 12, 13, 56],
[57, 58, 59, 60, 61, 62, 14, 15],
]
)
)
两个递增数列中查找数
已知数列 A A A由两个递增数列组成,即 A = a 1 , a 2 , … , a c , a c + 1 , … , a n A={a_1, a_2, \dots, a_c, a_{c+1}, \dots,a_n} A=a1,a2,…,ac,ac+1,…,an,其中 { a 1 , a 2 , … , a c } \{a_1, a_2, \dots, a_c\} {a1,a2,…,ac}和 { a c + 1 , … , a n } \{a_{c+1}, \dots,a_n\} {ac+1,…,an}是递增数列,且 a 1 > a n a_1>a_n a1>an。现在需要从 A A A中查找一个数。
# -*- coding: utf-8 -*-
import random
def find_num(A, target):
# print(A)
n = len(A)
if n == 0:
return -999
if n == 1:
return 0 if A[0] == target else -999
m = n >> 1
if A[0] > target:
# A[0] > target,目标在第2段上,需要确定分割的位置
if A[m] == target:
return m
elif A[m] > target:
# A[m] > target,仍然需要确定分割的位置
if A[m] > A[0]:
# A[m] > A[0] > target,分割位置在m之后,目标在m之后
return m + 1 + find_num(A[m + 1 : n], target)
else:
# target < A[m] < A[0],分割位置在m之前,又A[m] > target 目标在m之前
return find_num(A[0:m], target)
else:
# A[m] < target < A[0], 故分割位置在m之前, 目标在m之后
return m + 1 + find_num(A[m + 1 : n], target)
else:
# A[0] < target, 目标在第1段上,需要确定分割的位置
if A[m] == target:
return m
elif A[m] > target:
# A[m] > target > A[0], 故分割位置在第2段,但目标在m之前
return find_num(A[0:m], target)
else:
# A[m] < target,仍然需要确定分割的位置
if A[m] > A[0]:
# target > A[m] > A[0],分割位置在m之后,目标在m之后
return m + 1 + find_num(A[m + 1 : n], target)
else:
# A[m] < A[0] < target,分割位置在m之前,目标在m之前
return find_num(A[0:m], target)
if __name__ == "__main__":
for _ in range(1000):
b = random.randint(1, 99)
B = list(range(1, b + 1))
a = random.randint(1, 99)
A = list(range(b + 100, b + 100 + a + 1))
C = A + B
c = random.choice(C)
print("C = ", C)
print("c = ", c)
print(find_num(C, c))
1-N中寻找缺失的数字
A A A是从 { 1 , 2 , … , n } \{1, 2, \dots, n\} {1,2,…,n}中任意剔除一个数字后组成的数组,现需要寻找 A A A中缺失的数字
def findlostnum(nums, s=0, e=None):
if e is None:
e = len(nums) - 1
l = e - s + 1
# print(nums[s:e+1], l)
if l == 0:
return 1
elif l == 1:
return s+1 if nums[s] != s+1 else len(nums)+1
m = (l-1) >> 1
if nums[m + s] > m + s + 1:
return findlostnum(nums, s, m + s)
else:
return findlostnum(nums, m + s + 1, e)
print(findlostnum([2,3,4,5,6])==1)
print(findlostnum([1,3,4,5,6])==2)
print(findlostnum([1,2,4,5,6])==3)
print(findlostnum([1,2,3,5,6])==4)
print(findlostnum([1,2,3,4,6])==5)
print(findlostnum([1,2,3,4,5])==6)