面試_第K問題

215. 數組中的第K個最大元素

給定整數數組 nums 和整數 k,請返回數組中第 k 個最大的元素。

請注意,你需要找的是數組排序後的第 k 個最大的元素,而不是第 k 個不同的元素。

示例 1:

輸入: [3,2,1,5,6,4] 和 k = 2
輸出: 5
示例 2:

輸入: [3,2,3,1,2,4,5,5,6] 和 k = 4
輸出: 4

提示:

1 <= k <= nums.length <= 104
-104 <= nums[i] <= 104
class Solution:

    def findKthLargest(self, nums: List[int], k: int) -> int:
        # start, end = 0, len(nums)
        # if end == 1:
        #     return nums[0]
        # if k > end:
        #     return -1
       
        # def partition(low, high):
        #     m = randint(low, high)
        #     nums[low], nums[m] = nums[m], nums[low]
        #     qivot = nums[low]
        #     # 降序
        #     while low < high:
        #         while low < high and nums[high] <= qivot: high -= 1
        #         nums[low] = nums[high]
        #         while low < high and nums[low] >= qivot: low += 1
        #         nums[high] = nums[low]
        #     nums[low] = qivot
        #     return low

        # def qsort(low, high):
        #     pivotloc = partition(low, high)
        #     if pivotloc >  k - 1:
        #         return qsort(low, pivotloc - 1)
        #     elif pivotloc < k - 1:
        #         return qsort(pivotloc + 1, high)
        #     return nums[k - 1]

        # return qsort(start, end - 1)

        start, end = 0, len(nums)
        if k > end:
            return -1
       
        def partition(low, high):
            m = randint(low, high)
            nums[low], nums[m] = nums[m], nums[low]
            qivot = nums[low]
            # 升序
            while low < high:
                while low < high and nums[high] >= qivot: high -= 1
                nums[low] = nums[high]
                while low < high and nums[low] <= qivot: low += 1
                nums[high] = nums[low]
            nums[low] = qivot
            return low

        def qsort(low, high):
            pivotloc = partition(low, high)
            # 因爲是升序,第k大數是,n - k
            if pivotloc >  end - k:
                return qsort(low, pivotloc - 1)
            elif pivotloc < end - k:
                return qsort(pivotloc + 1, high)
            return nums[end - k]

        return qsort(start, end - 1)

時間複雜度:O(n);空間複雜度:O(logn)
法二:大頂堆

class Solution {
public:
    void maxHeapify(vector<int>& a, int i, int heapSize) {
        int l = i * 2 + 1, r = i * 2 + 2, largest = i;
        if (l < heapSize && a[l] > a[largest]) {
            largest = l;
        } 
        if (r < heapSize && a[r] > a[largest]) {
            largest = r;
        }
        if (largest != i) {
            swap(a[i], a[largest]);
            maxHeapify(a, largest, heapSize);
        }
    }

    void buildMaxHeap(vector<int>& a, int heapSize) {
        for (int i = heapSize / 2; i >= 0; --i) {
            maxHeapify(a, i, heapSize);
        } 
    }

    int findKthLargest(vector<int>& nums, int k) {
        int heapSize = nums.size();
        buildMaxHeap(nums, heapSize);
        for (int i = nums.size() - 1; i >= nums.size() - k + 1; --i) {
            swap(nums[0], nums[i]);
            --heapSize;
            maxHeapify(nums, 0, heapSize);
        }
        return nums[0];
    }
};

時間複雜度:O(nlogn)
空間複雜度:O(logn)

面試題40. 最小的k個數

輸入整數數組 arr ,找出其中最小的 k 個數。例如,輸入4、5、1、6、2、7、3、8這8個數字,則最小的4個數字是1、2、3、4。

示例 1:

輸入:arr = [3,2,1], k = 2
輸出:[1,2] 或者 [2,1]
示例 2:

輸入:arr = [0,1,2,1], k = 1
輸出:[0]

限制:

0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000
class Solution:
    # def selectPartition(self, arr, low, high):
    #     mid = (low + high) // 2
    #     if arr[mid] > arr[high]:
    #         arr[mid], arr[high] = arr[high], arr[mid]
    #     if arr[low] > arr[high]:
    #         arr[low], arr[high] = arr[high], arr[low]
    #     if arr[mid] > arr[low]:
    #         arr[mid], arr[low] = arr[low], arr[mid]

    def partition(self, arr, low, high):
        # self.selectPartition(arr, low, high)
        # m = (low + high) // 2
        m = randint(low, high)
        arr[low], arr[m] = arr[m], arr[low]
        pivot = arr[low]
        while low < high:
            while low < high and arr[high] >= pivot: high -=1
            arr[low] = arr[high]
            while low < high and arr[low] <= pivot: low += 1
            arr[high] = arr[low]
        arr[low] = pivot
        return low
    
    def selectTopK(self, arr, low, high, k):
        pivotloc = self.partition(arr, low, high)
        if pivotloc < k - 1:
            return self.selectTopK(arr, pivotloc + 1, high, k)
        elif pivotloc > k - 1:
            return self.selectTopK(arr, low, pivotloc - 1, k)

        return arr[:k]
        
    def getLeastNumbers(self, arr, k):
        alen = len(arr)
        if k == 0 or k > alen:
            return []
        if alen == 0:
            return []
        
        return self.selectTopK(arr, 0, alen - 1, k)

時間複雜度:O(n), 空間複雜度:O(logn)


## [劍指 Offer 22. 鏈表中倒數第k個節點](https://leetcode.cn/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/)

輸入一個鏈表,輸出該鏈表中倒數第k個節點。爲了符合大多數人的習慣,本題從1開始計數,即鏈表的尾節點是倒數第1個節點。

例如,一個鏈表有 6 個節點,從頭節點開始,它們的值依次是 1、2、3、4、5、6。這個鏈表的倒數第 3 個節點是值爲 4 的節點。

示例:

給定一個鏈表: 1->2->3->4->5, 和 k = 2. 返回鏈表 4->5.

```c++
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* getKthFromEnd(ListNode* head, int k) {
        if (head == nullptr) {
            return nullptr;
        }
        
        ListNode *slow = head, *fast = head;
        for (int i = 0; i < k && fast; i++)
        {
            fast = fast->next;
        }
        while (slow && fast)
        {
            slow = slow->next; fast = fast->next;
        }
        return slow;
    }
};

劍指 Offer 54. 二叉搜索樹的第k大節點

給定一棵二叉搜索樹,請找出其中第 k 大的節點的值。

示例 1:

輸入: root = [3,1,4,null,2], k = 1
3
/
1 4

2
輸出: 4
示例 2:

輸入: root = [5,3,6,2,4,null,null,1], k = 3
5
/
3 6
/
2 4
/
1
輸出: 4

限制:

1 ≤ k ≤ 二叉搜索樹元素個數
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    int ans;
    int cur;
public:
    void dfs(TreeNode* root)
    {
        if (root == nullptr) {
            return;
        }
        dfs(root->right);
        if (cur == 0) {
            return;
        }
        cur--;
        if (cur == 0) {
            ans = root->val;
            return;
        }
        dfs(root->left);
    }
    int kthLargest(TreeNode* root, int k) {
        cur = k;
        dfs(root);

        return ans;
    }
};

時間複雜度:O(n)
空間複雜度:O(n)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章