• [jobdu]最小的K个数


    一开始马上想起来寻找第k小的数,是采用快排的partition方法。但因为题目要把k之前的数排序输出,这个方法就不是很合适,因为(随机化后:http://blog.csdn.net/liangbopirates/article/details/9377105)它最差能在O(n)找到第k小的数,那么就要最差k*O(n)。如果对前面部分排序那就是O(k*logk) + O(n)了。都不合适,看来最合适的还是使用堆,能做到O(n*logK)。

    但partition方法和堆方法比较,有个好处就是inplace,不占多余内存,在海量数据处理的时候有这个好处。

    下面这段代码是寻找第k小的数,其精华部分是partition方法,注意这个方法的写法,维基百科和算法导论上都是这样的,比一般的写法简洁,需要记下来。本质是分了三段,第一段小于等于pivot,第二段大于pivot,第三段是未处理的。idx一直指向第二段的第一个,或者说第一段最右边过去一个,i一直指向第二段的最右边,或是第三段的最左边。那么当a[i]<pivot的时候,就把a[i]和a[idx]交换,然后idx++,这样就继续保持了这个性质。

    #include <iostream>
    using namespace std;
    
    void swap(int& a, int& b)
    {
    	int tmp = a;
    	a = b;
    	b = tmp;
    }
    
    // start、end分别为数组第一个元素和最后一个元素的索引
    int partition(int arr[], int start, int end)
    {
        int pivot = arr[end];
        int idx = start;
        //这个循环比一般的写法简洁高效,维基百科上和算法导论上的
        for(int i = start; i < end; i++) {
            if(arr[i] < pivot) {
                swap(arr[i], arr[idx]);
                ++idx;
            }
        }
        swap(arr[idx], arr[end]);
        return idx;
    }
    
    int main()
    {
    	int n; // count
    	cin >> n;
    	int m; // index
    	cin >> m;
    	int* a = new int[n];
    	for (int i = 0; i < n; i++)
    	{
    		cin >> a[i];
    	}
    	int start = 0;
    	int end = n - 1;
    	while (true)
    	{
    		int c = partition(a, start, end);
    		if (c == (m-1))
    		{
    			break;
    		}
    		if (c > (m - 1))
    		{
    			end = c - 1;
    		}
    		else
    		{
    			start = c + 1;
    		}
    	}
    	cout << a[m-1] << endl;
    	delete[] a;
    	system("pause");
    }
    

    下面是采取堆的方式,(待续):

  • 相关阅读:
    json_encode([0])
    try catch throw
    如何 lookback
    协程||进程
    客户错了?
    循环 php 变量会影响到传入的参数
    csv变成xls, csv乱码
    虚拟机不能git push
    数组下标大小写
    php 静态方法
  • 原文地址:https://www.cnblogs.com/lautsie/p/3293135.html
Copyright © 2020-2023  润新知