欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

九章算法 | 字节跳动面试题:无序数组K小元素

程序员文章站 2022-07-14 12:20:33
...

找到一个无序数组中第K小的数。

在线评测地址:LintCode 领扣

样例 1:

        输入: [3, 4, 1, 2, 5], k = 3
输出: 3
      

样例 2:

        输入: [1, 1, 1], k = 2
输出: 1
      

【题解】

最容易想到的就是直接排序,返回第k大的值。时间复杂度是O(nlogn),这里提供O(n)的解法。

这题其实是快速排序算法的变体,通过快速排序算法的partition步骤,可以将小于pivot的值划分到pivot左边,大于pivot的值划分到pivot右边,所以可以直接得到pivotrank。从而缩小范围继续找第k大的值。

partition步骤:

  1. left = startright = endpivot = nums[left]
  2. nums[left] < pivot时,left指针向右移动。
  3. nums[right] > pivot时,right指针向左移动。
  4. 交换两个位置的值,right指针左移,left指针右移。
  5. 直到两指针相遇,否则回到第2步。

每次partition后根据pivot的位置,寻找下一个搜索的范围。

复杂度分析

设数组长度为n

时间复杂度 O(n)

  • 对一个数组进行partition的时间复杂度为O(n)
  • 分治,选择一边继续进行partition
  • 所以总的复杂度为T(n) = T(n / 2) + O(n),总时间复杂度依然为O(n)

空间复杂度 O(1)

  • 只需要快速选择游标的O(1)额外空间。
        public class Solution {
    /**
     * @param k: An integer
     * @param nums: An integer array
     * @return: kth smallest element
     */
    public int kthSmallest(int k, int[] nums) {
        int n = nums.length;
        // 数组从0开始标号,要传k - 1
        return partition(nums, 0, n - 1, k - 1);
    }
    private int partition(int[] nums, int start, int end, int k) {
        int left = start, right = end;
        int pivot = nums[left];
        
        while (left <= right) {
            while (left <= right && nums[left] < pivot) {
                left++;
            }
            while (left <= right && nums[right] > pivot) {
                right--;
            }
            if (left <= right) {
                swap(nums, left, right);
                left++;
                right--;
            }
        }
        
        // 如果第 k 小在右侧,搜索右边的范围,否则搜索左侧。
        if (k <= right) {
            return partition(nums, start, right, k);
        }
        if (k >= left) {
            return partition(nums, left, end, k);
        }
        return nums[k];
    }
    private void swap(int[] nums, int x, int y) {
        int temp = nums[x];
        nums[x] = nums[y];
        nums[y] = temp;
    }
}
      

更多题解参见:九章算法