topK问题

»数据结构与算法

无序数组中找topK问题

例如给一个无序数组,需要找到其中前100大的数。

思路:

有序数组中topK问题

如果给一有序数组,需要找其中前K大的数

思路:

如果给定两个有序数组,需要找到其中前K大的数

思路:

数组中找中位数问题

给定一无序数组,需要找到其中的中位数

思路:

如果给定两个有序数组,需要找到其中的中位数 思路:

代码:

class Solution {
    // 寻找两个有序数组的中位数
    // 问题转换为求第K小的数
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if(nums1 == null || nums1.length == 0){
            // 求nums2的中位数
            return nums2.length % 2 == 0 
            ? (nums2[nums2.length / 2] + nums2[nums2.length / 2 - 1]) / 2.0 
            : nums2[nums2.length / 2];
        }
        if(nums2 == null || nums2.length == 0){
            return nums1.length % 2 == 0 
            ? (nums1[nums1.length / 2] + nums1[nums1.length / 2 - 1]) / 2.0 
            : nums1[nums1.length / 2];
        }
        int len = nums1.length + nums2.length;
        return len % 2 == 0 
        ? (topK(nums1,nums2,0,0,len/2)+topK(nums1,nums2,0,0,len/2+1))/2.0 
        : topK(nums1,nums2,0,0,len/2 + 1);
    }

    // 找两个有序数组的第k小的数
    // 1 3 5 7 9
    // 2 4 6 8 10
    // 思路:逐步减小k,并且每次减少的幅度k / 2
    public int topK(int[] nums1,int[] nums2,int start1,int start2,int k){
        if(start1 >= nums1.length){
            return nums2[start2 + k - 1]; // 这里注意需要下标减1
        }
        if(start2 >= nums2.length){
            return nums1[start1 + k - 1];
        }

        if(k == 1){ // 转换成了两个有序数组中找第一小的数
            return Math.min(nums1[start1] , nums2[start2]);
        }

        if(start1 + k / 2 > nums1.length){ // 肯定不会在nums2的前 k / 2
            return topK(nums1,nums2,start1,start2 + k / 2,k - k / 2);
        }else if(start2 + k / 2 > nums2.length){
            return topK(nums1,nums2,start1 + k / 2,start2,k - k / 2);
        }

        int mid1 = nums1[start1 + k / 2 - 1];
        int mid2 = nums2[start2 + k / 2 - 1];
        if(mid1 > mid2){ // 移除nums2的前 k / 2
            return topK(nums1,nums2,start1,start2 + k / 2,k - k / 2);
        }else {
            return topK(nums1,nums2,start1 + k / 2,start2,k - k/2);
        }
    }
}