Algorithm 访谈问题-在未排序的数组中查找kthsmalle元素

Algorithm 访谈问题-在未排序的数组中查找kthsmalle元素,algorithm,Algorithm,这要求在非负整数的未排序数组中找到第k个最小元素 这里的主要问题是内存限制:(这里我们可以使用恒定的额外空间 首先,我尝试了一个O(n^2)方法[没有任何额外内存],它给了我TLE 然后我尝试使用优先级队列[额外内存],这给了我MLE:( 你知道如何在时间限制内用恒定的额外空间来解决这个问题吗。你可以使用一个O(n^2)方法进行一些修剪,这将使程序像O(nlogn):) 声明两个变量low=位置小于k的最大值high=位置大于k的最小值 跟踪已处理的低值和高值 每当新值出现时,检查它是否在[低、

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

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

首先,我尝试了一个
O(n^2)
方法[没有任何额外内存],它给了我
TLE

然后我尝试使用
优先级队列
[额外内存],这给了我
MLE
:(

你知道如何在时间限制内用恒定的额外空间来解决这个问题吗。

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

  • 声明两个变量
    low=位置小于k的最大值
    high=位置大于k的最小值
  • 跟踪已处理的
    低值
    高值
  • 每当新值出现时,检查它是否在
    [低、高]
    边界内。如果
    则处理它,否则跳过该值
  • 就是这样:)我想它将通过
    TLE
    MLE
    :)

    看看我的代码:

    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];
        }
    }
    
    int低=0,高=1e9;
    对于(int i=0;i=low&&A[i]k)
    打破
    }
    if(cnt+cnt1=k)
    高=A[i]-1;
    if(cnt=k)
    {
    返回一个[i];
    }
    }
    
    您可以就地执行

    其思想类似于,但仅在数组的相关部分递归,而不是全部递归。注意,该算法可以很容易地用O(1)额外的空间来实现,因为它的递归调用是一个复杂的过程


    这将导致平均情况下的
    O(n)
    解决方案(请确保随机选择一个轴,以确保您不会陷入预先设计的边缘情况,如排序列表)。这可以改进为最坏情况
    O(n)
    使用,但常数明显更差。

    对问题的答案进行二进制搜索

    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        
    
    start=0,end=2^31-1
    当启动k时
    结束=x-1
    elif小于k
    开始=x+1
    其他的
    ans=x
    结束=x-1
    返回ans
    

    希望这有帮助

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

    它通过了InterviewBit的所有测试

    下面是代码(Java):

    public int kthsmallest(最终列表a,int k){
    int lo=整数最小值;
    int hi=整数最大值;
    int champ=-1;
    对于(int i=0;ilo&&iValk&&iVallo)lo=iVal;
    如果(计数>=k&&(champ==-1 | | iVal
    你不能对数组进行排序吗?你也在考虑递归空间吗?@GiorgiNakeuri不,我不能对数组进行排序array@sonukumar对虽然我得到了解决办法。阿里·阿克伯的回答涵盖了我的要求。现在是AC:)递归所需的空间呢?@sonukumar递归完成时-平均情况下为对数。它也可以通过记忆索引,在常量空间中进行迭代。无论如何,大多数编译器都会为您进行此优化,因为
    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;
    }