归并排序 - 从二路到多路刷题

基础知识思想

思路:
处理左边 得到左边的信息
处理右边 得到右边的信息
完成合并过程 得到横跨两边的信息

剑指 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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值