Algorithm-Revisit the problem of the median of unordered arrays

Algorithm-Revisit the problem of the median of unordered arrays

Algorithm-Revisit the problem of the median of unordered arrays

Given an unordered array, find the median of the unordered array

This question mentioned algorithm-TopK related issues in the blog I wrote earlier . It can be implemented with a heap or with a fast selection algorithm. When using the quick selection algorithm, we will discuss two situations. One is when the number of array elements is odd, we can directly select the middle element, and the other is when the number is even, we make two quick selections.

However, in the above method, when the number of array elements is even, it does not pay attention to the impact of the first quick selection on the array, resulting in the time complexity of the second quick selection may reach O(N^2)

In fact, we can use the nature of fast selection to reduce the time complexity of the second selection to O(k-1)

The principle of quick selection is to adjust the pivot element to position k-1. Finally, the element on the left of the pivot element is greater than or equal to the pivot element and the element on the right is less than or equal to the pivot element, or vice versa.

When we select the k-th largest element, in fact, we can determine that the k-1 largest element is in the left half or the right half of the pivot element.

To select the K-th largest element as an example, we select the array in descending order.

1. When the array length is even, we need to select the element with the largest nums.length/2+1 (denoted as m1) and the element with the largest nums.length/2 (denoted as m2). After we choose m1, we can determine that m2 is in the left half of k-1, and because the left half is all greater than m1, the problem becomes to find the minimum value in the interval [0,k-1), that is m2, we can traverse the elements of the interval directly to find the minimum m2. The final result is (m1+m2)/2.

2. When the length of the array is odd, we directly select the element with the largest nums.length/2+1 (denoted as m1), and m1 is the median we are looking for

In this way, we can get a faster and simpler code:

    @Test
    public void test(){
    
    
        int[] nums={
    
    7,5,9,3,11,32,27,1,-9,4};
        //-9,1,3,4,5,7,9,11,27,32
        System.out.println(mediumNUmberOfMixArray(nums));
    }


    public int mediumNUmberOfMixArray(int[] nums){
    
    
        int k=nums.length/2+1;
        quickSelect(nums,0,nums.length-1,k);
        int m1=nums[k-1];
        if(nums.length%2==1){
    
    
            return m1;
        }else {
    
    
            int m2=Integer.MAX_VALUE;
            for (int i=0;i<k-1;i++){
    
    
                m2=Math.min(m2,nums[i]);
            }
            return (m1+m2)/2;
        }

    }
    public void quickSelect(int[] nums,int left,int right,int k){
    
    
        if(left<right){
    
    
            int i=left,j=right;
            int pivot=nums[left];
            while (i<j){
    
    
                while (i<j&&nums[j]<=pivot){
    
    
                    j--;
                }
                while (i<j&&nums[i]>=pivot){
    
    
                    i++;
                }
                if(i<j){
    
    
                    swap(nums,i,j);
                }
            }
            swap(nums,i,left);//恢复枢纽元
            if(i>=k){
    
    
                quickSelect(nums,left,i-1,k);
            }else {
    
    
                quickSelect(nums,i+1,right,k);
            }
        }
    }

    private void swap(int[] nums, int i, int j) {
    
    
        int temp=nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }

Guess you like

Origin blog.csdn.net/qq_23594799/article/details/107594626