How to find kth smallest integer in an unsorted array without sorting the array?

心已入冬 提交于 2020-07-05 03:34:06

问题


So I am given an (unsorted) array A of N distinct integers, I am trying to implement a divide-and-conquer algorithm to find the Kth smallest element (K ≤ N) in the array (i.e. it would be the overall smallest if K=1). The algorithm returns the value of the Kth smallest element in the array. I need it to run in O(N) time in the average case. Could anyone give me some hints?


回答1:


Sephy, I'm going to walk this through very carefully. You always have to be careful when helping people with algorithms, because, and I cannot stress this enough, solving algorithm problems are to programmers what weight-lifting is to professional athletes. Knowing how to put yourself into the mode of thinking like a computer is what you will get paid to do in a few years. So if the solutions are just given to you, you're going to be the guy that bounces from job to job every 6 months instead of the guy who becomes the lead developer, or goes out on his own with a successful company.

Now that that rant is out of the way...

Traditionally, we think of algorithms that loop through the array once, and loop through it differently based on the first result, and repeat until we met some condition, to be O(n^2). Things that meet this criteria are selection sort, insertion sort, and bubble sort.

But it doesn't have to be. If we can properly divide the array into segments and prove the size of those segments, we can keep it on a low order.

And, with most divide and conquer algorithms, we can start in the middle.

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.

What do we know about A-small and A large? Are they the same size? Maybe, but probably not.

Is size(A-small) > k? or is it < k?

If size(A-small) == k - 1, wouldn't that make M the kth smallest element?

Is there something we can do to create a new value for k and do some recurrsion here?

I'm not going to finish this for you, because there should be plenty to chew on. These are the questions you need to ask yourself. @templatetypedef is 100% on the right track, this is just expanding on it.

If you have some more questions, ask them, but there should be enough here to allow you to solve it without robbing you of your mental exercise.




回答2:


As a hint, think about how the quicksort partition step works. It splits the input up so that the pivot is in its final position, smallest elements are to the left, and larger elements are to the right. Given this information, and knowing what index you were trying to find, could you think of a way to recursively find the kth element?




回答3:


Count the occurrences of each integer in the array in another array.




回答4:


For such classic problems, wikipedia works very well... See Selection algorithm on wikipedia




回答5:


try searching for the selection algorithm, or the selection sort algorithm




回答6:


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]);
        }

    }

}

Time Complexcity is almost O(N).




回答7:


Here is my code. This is an O(n) solution. I didn't find anything good online, so I decided to post this here. Hope you find it helpful.

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




来源:https://stackoverflow.com/questions/5011177/how-to-find-kth-smallest-integer-in-an-unsorted-array-without-sorting-the-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!