如何在未排序数组的情况下找到未排序数组中的第k个最小整数?

时间:2011-02-16 00:31:19

标签: arrays algorithm language-agnostic selection big-o

所以我得到一个N个不同整数的(未排序的)数组A,我试图实现一个分而治之的算法来找到数组中的第K个最小元素(K≤N)(即它将是如果K = 1则整体最小。该算法返回数组中第K个最小元素的值。我需要它在平均情况下在O(N)时间内运行。有人能给我一些提示吗?

7 个答案:

答案 0 :(得分:13)

塞菲,我要小心翼翼地走过去。在帮助人们使用算法时,你总是要小心,因为,我不能强调这一点,解决算法问题对程序员来说是专业运动员的举重。知道如何将自己置于像计算机这样的思维模式中,您将在几年内获得报酬。因此,如果解决方案只是给你,那么你将会成为每6个月从一个工作岗位跳槽而不是成为首席开发人员的人,或者是一个成功的公司独自出去的人。

现在那种咆哮已经不在了......

传统上,我们考虑循环数组一次的算法,并根据第一个结果以不同方式循环,并重复直到我们遇到某些条件,为O(n ^ 2)。符合此条件的内容包括选择排序,插入排序和冒泡排序。

但它不一定是。如果我们可以正确地将数组划分为段并证明这些段的大小,我们可以将它保持在低位。

而且,对于大多数分而治之的算法,我们可以从中间开始。

Let A be an array of size N with N distinct elements in it.

Let M be the element that resides at A[N/2]

Let A-large be an array of all elements greater than M.
Let A-small be an array of all elements less than M.

我们对A-small和A large有什么了解?它们的大小相同吗?也许,但可能不是。

size(A-small) > k?还是< k

如果size(A-small) == k - 1,那不会使M成为第k个最小元素吗?

我们可以做些什么来为k创建一个新值并在这里做一些复发吗?

我不打算为你完成这个,因为应该有足够的东西来咀嚼。这些是您需要问自己的问题。 @templatetypedef在正确的轨道上是100%,这只是扩展它。

如果您还有其他问题,请向他们询问,但这里应该有足够的帮助您解决问题而不会让您失去精神锻炼。

答案 1 :(得分:8)

作为提示,请考虑快速排序分区步骤的工作原理。它将输入分开,使枢轴位于最终位置,最小元素位于左侧,较大元素位于右侧。有了这些信息,并且知道你想要找到什么索引,你能想到一种递归找到第k个元素的方法吗?

答案 2 :(得分:0)

计算另一个数组中数组中每个整数的出现次数。

答案 3 :(得分:0)

对于这样的经典问题,维基百科非常有效...... 见Selection algorithm on wikipedia

答案 4 :(得分:0)

尝试搜索选择算法或选择排序算法

答案 5 :(得分:0)

import java.util.Scanner;


public class JavaApplication1 {
 public static int findpivot(int a,int b,int c){
     //System.out.println("x");
      if(a > b){
        if(c > a){
            return a;
        }
        else if(c > b){
            return c;
        }
        else{
            return b;
        }
    }
    else{
        if(c > b){
            return b;
        }
        else if(c > a){
            return c;
        }
        else{
            return a;
        }
    }
}

public static void find(int arr[],int l,int r,int target){
    //System.out.println(1);
    if(l >= r){
        return;
    }
    int mid = (l+r)/2;
       // System.out.println(1);
    int pivot = findpivot(arr[mid],arr[l],arr[r]);
    int i = l;
    int j = r;
    while(i<=j){
        while(arr[i] < pivot)i++;
        while(arr[j] > pivot)j--;
        if(i<=j){
            int temp = arr[i];
                        arr[i] = arr[j];
                        arr[j] = temp;//
            i++;
            j--;
        }

    }
    if(target <= (i-1)){
        find(arr,0,i-1,target);
    }
    else{
        find(arr,i,r,target);
    }
}

    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        while(t-->0){
            int n = sc.nextInt();
            int arr[] = new int[n];
            for(int i = 0;i<n;i++){
                arr[i] = sc.nextInt();
            }
            int k = sc.nextInt();
            find(arr,0,n-1,k-1);
            System.out.println(arr[k-1]);
        }

    }

}

时间复杂度几乎是O(N)。

答案 6 :(得分:0)

这是我的代码。这是一个O(n)解决方案。我在网上找不到任何不错的东西,因此决定在此发布。希望对您有所帮助。

def Smallest(arr, k):
    # # The brute force method
    # if(len(arr)<k):
    #    return 0
    # diff = []
    # for i in range(len(arr)):
    #     for j in range(i+1, len(arr)):
    #         diff.append(abs(arr[i]-arr[j]))
    # sortedDiff = sorted(diff)
    # print(diff)
    # print(sortedDiff)
    # return sortedDiff[k-1]

    #Efficient method
    if(len(arr)<k):
            return 0
    # (i, j, minDiff, count) = (0, 1, arr[1]-arr[0], 0)
    (i, j, minDiff) = (0, 1, [])
    while(i < len(arr)):
        if(j>len(arr)-1):
            i+=1
            if(i==len(arr)-1):
                break
            j=i+1
        else:
            minDiff.append(abs(arr[i]-arr[j]))
            j+=1
    # print(minDiff)
    (minElement, count) = (minDiff[0], 0)
    for i in range(len(minDiff)):
        if(count<k):
            minElement = minDiff[i]
            count+=1
            # print(minElement, count)
            if(count==k):
                return minElement
            else:
                continue
        else:
            # print("This part is being hit")
            continue