找到无序数组中最小的k个数

//找到无序数组中最小的k个数
public class GetKOfArr{
	
	//方法一(堆排序方法,建立并维持含k个数的大根堆,时间复杂度为O(NlogK))
    public static int[]getMinKNumsByHeap(int[]arr,int k)
    {
    	if(k<1||k>arr.length)
    	{
    		return arr;
    	}

        int[]kheap=new int[k];
        //初始化一个堆的数据
        for(int i=0;i<k;i++)
        {
            heapInsert(kheap,arr[i],i);
        }

        for(int i=k;i!=arr.length;i++)
        { 
        	if(arr[i]<kheap[0])
        	{
        		kheap[0]=arr[i];
        		heapify(kheap,0,k);
        	}

        }
        
        return kheap;
    }
    //建立含有k个数的大根堆
    public static void heapInsert(int[]arr,int value,int index)
    {
    	 arr[index]=value;
    	 while(index!=0)
    	 {
    	 	int parent=(index-1)/2;
    	 	if(arr[parent]<arr[index])
    	 	{
    	 		swap(arr,parent,index);
    	 		index=parent;
    	 	}else
    	 	{
    	 		break;
    	 	}
    	 }

    }
    //调整含有k个数的大根堆
    public static void heapify(int[]arr,int index,int heapSize)
    {
          int left=index*2+1;
          int right=index*2+2;
          int largest=index;
          while(left<heapSize)
          {
          	 if(arr[left]>arr[index])
          	 {
          	 	largest=left;
          	 }
             if(right<heapSize&&arr[right]>arr[largest])
             {
             	largest=right;
             }
             if(largest!=index)
             {
             	swap(arr,largest,index);
             }else
             {
             	break;
             }
             index=largest;
             left=index*2+1;
             right=index*2+2;
          }

    }
  
  //****************************************************************************
	//方法二(经典线性查找算法(BFPRT算法),时间复杂度为O(N))
    public static int[] getMinKNumsByBFPRT(int[] arr, int k) {
		if (k < 1 || k > arr.length) {
			return arr;
		}
		int minKth = getMinKthByBFPRT(arr, k);
		int[] res = new int[k];
		int index = 0;
		for (int i = 0; i != arr.length; i++) {
			if (arr[i] < minKth) {
				res[index++] = arr[i];
			}
		}
		for (; index != res.length; index++) {
			res[index] = minKth;
		}
		return res;
	}

	public static int getMinKthByBFPRT(int[] arr, int K) {
		int[] copyArr = copyArray(arr);
		return select(copyArr, 0, copyArr.length - 1, K - 1);
	}

	public static int[] copyArray(int[] arr) {
		int[] res = new int[arr.length];
		for (int i = 0; i != res.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	public static int select(int[] arr, int begin, int end, int i) {
		if (begin == end) {
			return arr[begin];
		}
		int pivot = medianOfMedians(arr, begin, end);
		int[] pivotRange = partition(arr, begin, end, pivot);
		if (i >= pivotRange[0] && i <= pivotRange[1]) {
			return arr[i];
		} else if (i < pivotRange[0]) {
			return select(arr, begin, pivotRange[0] - 1, i);
		} else {
			return select(arr, pivotRange[1] + 1, end, i);
		}
	}

	public static int medianOfMedians(int[] arr, int begin, int end) {
		int num = end - begin + 1;
		int offset = num % 5 == 0 ? 0 : 1;
		int[] mArr = new int[num / 5 + offset];
		for (int i = 0; i < mArr.length; i++) {
			int beginI = begin + i * 5;
			int endI = beginI + 4;
			mArr[i] = getMedian(arr, beginI, Math.min(end, endI));
		}
		return select(mArr, 0, mArr.length - 1, mArr.length / 2);
	}
    //划分
	public static int[] partition(int[] arr, int begin, int end, int pivotValue) {
		int small = begin - 1;
		int cur = begin;
		int big = end + 1;
		while (cur != big) {
			if (arr[cur] < pivotValue) {
				swap(arr, ++small, cur++);
			} else if (arr[cur] > pivotValue) {
				swap(arr, cur, --big);
			} else {
				cur++;
			}
		}
		int[] range = new int[2];
		range[0] = small + 1;
		range[1] = big - 1;
		return range;
	}
    //获得中位数
	public static int getMedian(int[] arr, int begin, int end) {
		insertionSort(arr, begin, end);
		int sum = end + begin;
		int mid = (sum / 2) + (sum % 2);
		return arr[mid];
	}
    //插入排序
	public static void insertionSort(int[] arr, int begin, int end) {
		for (int i = begin + 1; i != end + 1; i++) {
			for (int j = i; j != begin; j--) {
				if (arr[j - 1] > arr[j]) {
					swap(arr, j - 1, j);
				} else {
					break;
				}
			}
		}
	}
     //两个数的交换
	public static void swap(int[] arr, int index1, int index2) {
		int tmp = arr[index1];
		arr[index1] = arr[index2];
		arr[index2] = tmp;
	}
    //打印数组
	public static void printArray(int[] arr) {
		for (int i = 0; i != arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}

	public static void main(String[]args)
	{
	  //System.out.println("Hello");
      int[] arr = { 6, 9, 1, 3, 1, 2, 2, 5, 6, 1, 3, 5, 9, 7, 2, 5, 6, 1, 9 };
	  // sorted : { 1, 1, 1, 1, 2, 2, 2, 3, 3, 5, 5, 5, 6, 6, 6, 7, 9, 9, 9 }
	  printArray(getMinKNumsByHeap(arr, 10));   //堆排序算法
	  printArray(getMinKNumsByBFPRT(arr, 5));  //BFPRT算法
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值