基础知识思想
思路:
处理左边 得到左边的信息
处理右边 得到右边的信息
完成合并过程 得到横跨两边的信息
剑指 Offer 51. 数组中的逆序对
class Solution:
def reversePairs(self, nums: List[int]) -> int:
def merge_sort(nums, l, r):
if l >= r:
return 0
mid = (l + r) // 2
ans1 = merge_sort(nums, l, mid)
ans2 = merge_sort(nums, mid + 1, r)
tem = [0] * (r - l + 1)
p1 = l
p2 = mid + 1
idx = 0
ans = ans1 + ans2
while p1 <= mid or p2 <= r:
if p2 > r or (p1 <= mid and nums[p1] <= nums[p2]):
tem[idx] = nums[p1]
p1 += 1
ans += p2 - (mid + 1)
else:
tem[idx] = nums[p2]
p2 += 1
idx += 1
nums[l : r + 1] = tem
return ans
return merge_sort(nums, 0, len(nums) - 1)
23. 合并K个升序链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
n = len(lists)
if n == 0:
return None
if n == 1:
return lists[0]
mid = n // 2
return self.merge(self.mergeKLists(lists[:mid]), self.mergeKLists(lists[mid:]))
def merge(self, left, right):
tmp = res = ListNode(0)
while left and right:
if left.val < right.val:
tmp.next, left = left, left.next
else:
tmp.next, right = right, right.next
tmp = tmp.next
tmp.next = left if left else right
return res.next
148. 排序链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head or not head.next:
return head
slow = head
fast = head.next
while fast and fast.next:
slow, fast = slow.next, fast.next.next
mid, slow.next = slow.next, None
left, right = self.sortList(head) , self.sortList(mid)
tmp = res = ListNode(0)
while left and right:
if left.val < right.val:
tmp.next, left = left, left.next
else:
tmp.next, right = right, right.next
tmp = tmp.next
tmp.next = left if left else right
return res.next
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode *mergeSort(ListNode *head, int n) {
if(head == nullptr || head->next == nullptr) return head;
int l = n / 2, r = n - l;
ListNode *lp = head, *rp = lp, *p;
for (int i = 1; i < l; i++, rp = rp->next);
p = rp, rp = rp->next;
p->next = nullptr;
lp = mergeSort(lp, l); // left sort
rp = mergeSort(rp, r); // right sort
ListNode ret;
p = &ret;
while(lp || rp) {
if((rp == nullptr) || (lp && lp->val <= rp->val)) {
p->next = lp;
lp = lp->next;
p = p->next;
} else {
p->next = rp;
rp = rp->next;
p = p->next;
}
}
return ret.next;
}
ListNode* sortList(ListNode* head) {
int n = 0;
ListNode *p = head;
while (p) p = p->next, n += 1;
return mergeSort(head, n);
}
};
1305. 两棵二叉搜索树中的所有元素
# 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 getAllElements(self, root1: TreeNode, root2: TreeNode) -> List[int]:
def get_help(root, v):
if not root:
return
get_help(root.left, v)
v.append(root.val)
get_help(root.right, v)
v1, v2 = [], []
get_help(root1, v1)
get_help(root2, v2)
i, j = 0, 0
result = []
while i < len(v1) and j < len(v2):
if v1[i] < v2[j]:
result.append(v1[i])
i += 1
else:
result.append(v2[j])
j += 1
result += v1[i:]
result += v2[j:]
return result
1508. 子数组和排序后的区间和
class Solution:
def rangeSum(self, nums: List[int], n: int, left: int, right: int) -> int:
a = []
idx = 0
for i in range(len(nums)):
heapq.heappush(a, (nums[i], idx, i, i))
idx += 1
ans = 0
mod = 1000000007
for i in range(1, right + 1):
tem = heapq.heappop(a)
if i >= left:
ans = (ans + tem[0] % mod) % mod
if tem[3] < n - 1:
heapq.heappush(a,(sum(nums[tem[2]:tem[3] + 1 + 1]), idx, tem[2], tem[3] + 1))
idx += 1
return ans
327. 区间和的个数
class Solution:
def countRangeSum(self, nums: List[int], lower: int, upper: int) -> int:
def count(nums, l1, r1, l2, r2, upper, lower):
ans = 0
j = l2
k1 = k2 = l1
while j <= r2:
a = nums[j] - upper
b = nums[j] - lower
while k1 <= r1 and nums[k1] < a:
k1 += 1
while k2 <= r1 and nums[k2] <= b:
k2 += 1
ans += k2 - k1
j += 1
return ans
def merge_sort(nums, l, r, upper, lower):
if l >= r:
return 0
mid = (l + r) // 2
ans1 = merge_sort(nums, l, mid, upper, lower)
ans2 = merge_sort(nums, mid + 1, r, upper, lower)
ans3 = count(nums, l, mid, mid + 1, r, upper, lower)
# ans3 = 0
p1 = l
p2 = mid + 1
tem = [0] * (r - l + 1)
idx = 0
while p1 <= mid or p2 <= r:
if p2 > r or (p1 <= mid and nums[p1] <= nums[p2]):
tem[idx] = nums[p1]
p1 += 1
else:
tem[idx] = nums[p2]
p2 += 1
idx += 1
nums[l: r + 1] = tem
return ans1 + ans2 + ans3
pre_nums = [0] * (len(nums) + 1)
for i in range(len(nums)):
pre_nums[i + 1] = pre_nums[i] + nums[i]
return merge_sort(pre_nums, 0, len(pre_nums) - 1, upper, lower)
315. 计算右侧小于当前元素的个数
class Solution:
def countSmaller(self, nums: List[int]) -> List[int]:
def merge_sort(nums, l, r, idx_list, count_idx):
if l >= r:
return
mid = (l + r) // 2
merge_sort(nums, l, mid, idx_list, count_idx)
merge_sort(nums, mid + 1, r, idx_list, count_idx)
nums1 = nums[l:mid + 1]
nums2 = nums[mid + 1: r + 1]
idx_list1 = idx_list[l: mid + 1]
idx_list2 = idx_list[mid + 1: r + 1]
i, j, idx = 0, 0, l
while i < len(nums1) and j < len(nums2):
if nums1[i] <= nums2[j]:
nums[idx] = nums1[i]
idx_list[idx] = idx_list1[i]
count_idx[idx_list[idx]] += j
i += 1
else:
nums[idx] = nums2[j]
idx_list[idx] = idx_list2[j]
j += 1
idx += 1
if j == len(nums2):
nums[idx: r + 1] = nums1[i:]
idx_list[idx: r + 1] = idx_list1[i:]
for i_idx in idx_list1[i:]:
count_idx[i_idx] += len(nums2)
else:
nums[idx: r + 1] = nums2[j:]
idx_list[idx: r + 1] = idx_list2[j:]
return
idx_list = list(range(len(nums)))
count_idx = [0] * len(nums)
merge_sort(nums, 0, len(nums) - 1, idx_list, count_idx)
return count_idx
53. 最大子数组和
dfs 分治讨论
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
max_num = -100001
res = [0]
j = 1
heap_top = 0
heapq.heapify(res)
preSum = [0 for _ in range(len(nums) + 1)]
for i in range(len(nums)):
preSum[i + 1] = preSum[i] + nums[i]
while j < len(preSum):
heap_top = res[0]
heapq.heappush(res, preSum[j])
tmp = preSum[j] - heap_top
if max_num < tmp:
max_num = tmp
j += 1
return max_num
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
for i in range(1, n): nums[i] += nums[i-1]
pre = 0
ans = float("-inf")
for num in nums:
ans = max(ans, num - pre)
pre = min(pre, num)
return ans
面试题 04.08. 首个共同祖先
# 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:
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 left and right:
return root
return left if left else right
1302. 层数最深叶子节点的和
# 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 deepestLeavesSum(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
queue = collections.deque()
queue.append(root)
while queue:
num = 0
for _ in range(len(queue)):
node = queue.popleft()
num += node.val
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return num