Leetcode brush questions must be reviewed II (Leetcode 912 215 315 53)

912. Sort array

Merge

def sortArray(self, nums: List[int]) -> List[int]:
        def merge_sort(nums, l, r):
            # Termination conditions
            if l >= r: return
            # Recursive partition array
            m = (l + r) // 2
            merge_sort(nums, l, m)
            merge_sort(nums, m + 1, r)
            # Merge subarrays
            tmp = nums[l:r + 1]       # Temporary storage of interval elements to be merged
            i, j = 0, m - l + 1       # The two pointers point to the first element of the left / right sub array respectively
            for k in range(l, r + 1): # Traverse and merge left / right subarrays
                if i == m - l + 1:
                    nums[k] = tmp[j]
                    j += 1
                elif j == r - l + 1 or tmp[i] <= tmp[j]:
                    nums[k] = tmp[i]
                    i += 1
                else:
                    nums[k] = tmp[j]
                    j += 1
        merge_sort(nums, 0, len(nums)-1)
        return nums

Summary: to be honest, I still remember the idea of merging and sorting in a week, but I have forgotten 80% of the specific code. After reading the answer of God K, I know I can't write it now. You need to write it again before you can remember it clearly. I even review quickly, rather than passing through the knowledge points one by one. After one, understand one and count one. Human nature is to be greedy for more and faster, which is not surprising. I feel that my willpower and physical fitness are almost to the limit. If I want to review 10 questions today, it is impossible to merge them now. So I decided to take a break and write it down tomorrow. Because I think if the interviewer asks about merging or quick scheduling, it's definitely not to let us write a new one, but will ask us some very specific details. If we don't understand it thoroughly, it's likely to fail. During the interview, there must be many details. If I am careless in my study or review, I will not be able to go to the best company. This is certain. If you want to go to the best company, you have to pay 120% of your efforts.

Quick row

def findKthLargest(self, nums: List[int], k: int) -> int:

        def quicksort(left, right, nums):
            if left >= right: return 
            pivot = nums[left]
            start, end = left, right
            while left < right:
                while left < right and nums[right] > pivot: right -= 1
                while left < right and nums[left] < pivot: left += 1
                nums[left], nums[right] = nums[right], nums[left]
            nums[left], pivot = pivot, nums[left]
            quicksort(start, right-1, nums)
            quicksort(left+1, end, nums)

        quicksort(0, len(nums)-1, nums)
        return nums[-k]    

Summary of experience: I really can't remember how to do it today. But now I can remember after reading the code. I'm going to go over all the sorting carefully tomorrow.

215. The kth largest element in the array

Given the integer array nums and integer k, please return the K largest element in the array.
Please note that you need to find the K largest element after the array is sorted, not the k different element.

import heapq
class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        que = []
        heapq.heapify(que)
        for num in nums:
            heapq.heappush(que, num)
            if len(que) > k:
                heapq.heappop(que)
        return que[0]

Summary of experience: for the previous code, the method I used was fast scheduling. I've been familiar with the big top pile used this time, and it's much faster as expected.

315. Calculate the number of elements on the right that are smaller than the current element

class Solution:
    def countSmaller(self, nums) -> List[int]:
        def merge(left, right, nums, res, temp, index):

            if left >= right: return
            mid = (left + right) // 2
            merge(0, mid, nums, res, temp, index)
            merge(mid+1, right, nums, res, temp, index)
            if nums[index[mid]] <= nums[index[mid + 1]]:
                return

            # merge
            for i in range(left, right + 1):
                temp[i] = index[i]

            i, j = left, mid - left + 1
            for k in range(left, right + 1):
                if i > mid:
                    index[k] = temp[j]
                    j += 1
                elif j > right:
                    index[k] = temp[i]
                    i += 1
                    res[index[k]] += (right - mid)
                elif nums[temp[i]] <= nums[temp[j]]:
                    index[k] = temp[i]
                    i += 1
                    res[index[k]] += (j - mid - 1)
                else:
                    index[k] = temp[j]
                    j += 1

        size = len(nums)
        if size == 0:
            return []
        elif size == 1:
            return nums[0]
        res = [0 for _ in range(size)]
        temp = [None for _ in range(size)]
        index = [i for i in range(size)]

        merge(0, size-1, nums, res, temp, index)
        return res

Summary of experience: this problem is difficult. I remember to use reverse order pairs when writing, but I'm still not good at using index arrays. I didn't understand it at that time. I still can't write it now. It seems that what I said before is right. If I don't understand it, I'll never write it. I read the reference answer several times and understood it better than the last time. But I still can't write it in one breath.

from typing import List


class Solution:

    def countSmaller(self, nums: List[int]) -> List[int]:
        size = len(nums)
        if size == 0:
            return []
        if size == 1:
            return [0]

        temp = [None for _ in range(size)]
        res = [0 for _ in range(size)]
        # Index array, function: when merging back, it is convenient to know which subscript element it is
        indexes = [i for i in range(size)]

        self.__merge_and_count_smaller(nums, 0, size - 1, temp, indexes, res)
        return res

    def __merge_and_count_smaller(self, nums, left, right, temp, indexes, res):
        if left == right:
            return
        mid = left + (right - left) // 2
        self.__merge_and_count_smaller(nums, left, mid, temp, indexes, res)
        self.__merge_and_count_smaller(nums, mid + 1, right, temp, indexes, res)

        if nums[indexes[mid]] <= nums[indexes[mid + 1]]:
            return
        self.__sort_and_count_smaller(nums, left, mid, right, temp, indexes, res)

    def __sort_and_count_smaller(self, nums, left, mid, right, temp, indexes, res):
        # [left,mid] pre ordered array
        # [mid+1,right] post ordered array

        # Copy first, then merge
        for i in range(left, right + 1):
            temp[i] = indexes[i]

        i = left
        j = mid + 1
        for k in range(left, right + 1):
            if i > mid:
                indexes[k] = temp[j]
                j += 1
            elif j > right:
                indexes[k] = temp[i]
                i += 1
                res[indexes[k]] += (right - mid)
            elif nums[temp[i]] <= nums[temp[j]]:
                indexes[k] = temp[i]
                i += 1
                res[indexes[k]] += (j - mid - 1)
            else:
                indexes[k] = temp[j]
                j += 1


if __name__ == '__main__':
    nums = [5, 2, 6, 1]
    solution = Solution()
    result = solution.countSmaller(nums)
    print(result)

After walking through the answer debug, I can understand it, but I don't quite understand it when count ing times. In addition, the index is still a little confused. Skip first. Go back and do it again.

53. Maximum subarray and

Give you an integer array nums. Please find a continuous sub array with the largest sum (the sub array contains at least one element) and return its maximum sum.
A subarray is a contiguous part of an array.

def maxSubArray(self, nums: List[int]) -> int:
        if not nums: return
        if len(nums) == 1: return nums[0]
        res, total = [], 0
        flag = None
        for num in nums:
            total += num
            if total < 0:
                total = 0
                continue
            else:
                flag = True
                res.append(total)
        return max(res) if flag else max(nums)

I still remember that this solution should be simple dynamic programming, but the topic says that recursive method can also be used. As for the case of negative numbers, I also thought carefully. If there is a positive number, it will return to that positive number in the end. If they are all negative numbers, the largest negative number will be returned. I used flag as a flag.

I read the recursive method and didn't understand it very well.

class Solution {
public:
    struct Status {
        int lSum, rSum, mSum, iSum;
    };

    Status pushUp(Status l, Status r) {
        int iSum = l.iSum + r.iSum;
        int lSum = max(l.lSum, l.iSum + r.lSum);
        int rSum = max(r.rSum, r.iSum + l.rSum);
        int mSum = max(max(l.mSum, r.mSum), l.rSum + r.lSum);
        return (Status) {lSum, rSum, mSum, iSum};
    };

    Status get(vector<int> &a, int l, int r) {
        if (l == r) {
            return (Status) {a[l], a[l], a[l], a[l]};
        }
        int m = (l + r) >> 1;
        Status lSub = get(a, l, m);
        Status rSub = get(a, m + 1, r);
        return pushUp(lSub, rSub);
    }

    int maxSubArray(vector<int>& nums) {
        return get(nums, 0, nums.size() - 1).mSum;
    }
};

Keywords: Algorithm leetcode

Added by chrbar on Tue, 25 Jan 2022 12:51:13 +0200