面试_第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个节点

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。

示例:

给定一个链表: 1->2->3->4->5, 和 k = 2. 返回链表 4->5.

/**
 * 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)

posted @ 2022-07-08 15:57  douzujun  阅读(41)  评论(0编辑  收藏  举报