采访问题 - 在未排序的数组中找到KTHSMALLEST元素

时间:2015-06-20 08:23:48

标签: algorithm

problem要求在未排序的非负整数数组中找到第k个最小元素。

这里的主要问题是内存限制:(这里我们可以使用恒定的额外空间。

首先,我尝试了O(n^2)方法[没有任何额外的记忆]给了我TLE 然后我尝试使用priority queue [额外记忆]给了我MLE :(

任何想法如何在持续的额外空间和时间限制内解决问题。

4 个答案:

答案 0 :(得分:2)

您可以使用O(n^2)方法进行一些修剪,这会使程序像O(nlogn) :)

  1. 声明两个变量low = maximum value which position is less than khigh = lowest value which position is greater than k
  2. 跟踪您已处理的lowhigh值。
  3. 每当新值出现时,请检查它是否在[low , high]边界内。如果yes则处理它,否则跳过该值。
  4. 那就是:)我认为它会通过TLEMLE:)

    看看我的代码:

    int low=0,high=1e9;
    for(int i=0;i<n;i++) // n is the total number of element
    {
        if(!(A[i]>=low&&A[i]<=high)) // A is the array in which the element are saved
          continue;
        int cnt=0,cnt1=0; // cnt is for the strictly less value and cnt1 for same value. Because value can be duplicate.
        for(int j=0;j<n;j++)
        {
            if(i!=j&&A[i]>A[j])
              cnt++;
            if(A[i]==A[j])
              cnt1++;
            if(cnt>k)
              break;
        }
        if(cnt+cnt1<k)
          low=A[i]+1;
        else if(cnt>=k)
          high=A[i]-1;
        if(cnt<k&&(cnt+cnt1)>=k)
        {
            return A[i];
        }
    }
    

答案 1 :(得分:0)

您可以执行就地Selection Algorithm

这个想法类似于quicksort,但只能在数组的相关部分进行递归,而不是全部。请注意,该算法可以很容易地用O(1)额外空间实现 - 因为它的递归调用是tail call

这导致O(n)解决方案的平均情况(只需确保随机选择一个支点,以确保您不会陷入预先设计的边缘情况,例如排序列表) 。使用median of median technique可以将其改进为最差情况O(n),但常量会更差。

答案 2 :(得分:0)

二进制搜索问题的答案。

这里有2个主要观察结果:

  • 假设数组中的所有值都是'int'类型,它们的范围可以定义为[0,2 ^ 31]。那将是你的搜索空间。
  • 给定值x,我总能告诉O(n)第k个最小元素是否小于x或大于x。

粗略的伪代码:

start = 0, end = 2^31 - 1
while start <= end
  x = (start + end ) / 2
  less = number of elements less than or equal to x
  if less > k
    end = x - 1
  elif less < k
    start = x + 1
  else
    ans = x
    end = x - 1 
return ans        

希望这会有所帮助。

答案 3 :(得分:0)

我相信我找到了一个类似于@AliAkber的解决方案,但稍微容易理解(我跟踪的变量较少)。

它通过了InterviewBit的所有测试

这里是代码(Java):

public int kthsmallest(final List<Integer> a, int k) {
    int lo = Integer.MIN_VALUE;
    int hi = Integer.MAX_VALUE;
    int champ = -1;

    for (int i = 0; i < a.size(); i++) {
        int iVal = a.get(i);
        int count = 0;

        if (!(iVal > lo && iVal < hi)) continue;

        for (int j = 0; j < a.size(); j++) {
            if (a.get(j) <= iVal) count++;

            if (count > k) break;
        }

        if (count > k && iVal < hi) hi = iVal;
        if (count < k && iVal > lo) lo = iVal;

        if (count >= k && (champ == -1 || iVal < champ))
            champ = iVal;  
    }

    return champ;
}