-
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
何海涛:《剑指Offer:名企面试官精讲典型编程题》:九度OJ
题目描述:
-
输入:
-
每个测试案例包括2行:
第一行为2个整数n,k(1<=n,k<=200000),表示数组的长度。
第二行包含n个整数,表示这n个数,数组中的数的范围是[0,1000 000 000]。
-
输出:
-
对应每个测试案例,输出最小的k个数,并按从小到大顺序打印。
-
样例输入:
-
8 4
4 5 1 6 2 7 3 8
- #include <stdio.h>
- #include <stdlib.h>
- void quick(int data[], int low, int high ,int k)
- {
- int i = low, j = high, tmp = data[low];
- if (low < high)
- {
- // if是随机一个 准点,那么与第一个交换在处理就是咯~
- // Swap(data[low], data[(low + high) / 2]); //将中间的这个数和第一个数交换
- while (i < j)
- {
- while(i < j && data[j] >= tmp) // 从右向左找第一个小于tmp的数,等于tmp跳过
- {
- j--;
- }
- if(i < j) // 这个判断是需要的~
- {
- data[i++] = data[j];
- }
- while(i < j && data[i] < tmp) // 从左向右找第一个大于等于tmp的数
- {
- i++;
- }
- if(i < j)
- {
- data[j--] = data[i];
- }
- }
- data[i] = tmp; // 原数据归位到中间
- if( i == k ) // 已经出处理了K个
- {
- return;
- }
- quick(data, low, i - 1, k); // 递归调用
- if( i > k ) // if左边的个数已经足够,那么右边的处理就可以省略了,因为左边已经包含K个数
- {
- return ;
- }
- quick(data, i + 1, high, k);
- }
- }
- int main()
- {
- int * data, i, n, k;
- while( scanf("%d%d", &n, &k) != EOF )
- {
- data = ( int* )malloc( sizeof( int ) * n );
- for( i = 0; i < n; i++ )
- {
- scanf("%d", &data[i]);
- }
- quick( data, 0, n - 1, k );
- for( i = 0; i < k; i++ )
- {
- printf("%d ", data[i]);
- }
- printf("\n");
- free( data );
- }
- return 0;
- }
- // 小根堆( 堆是完全二叉树,所以用数组可以! )
- #include <stdio.h>
- void swap( int *data, int *b )
- {
- int t = *data;
- *data = *b;
- *b = t;
- }
- void adjust_heap(int *data,int i,int n) //调整堆
- {
- int lc = 2 * i; //i的左孩子节点序号
- int rc = 2 * i + 1; //i的右孩子节点序号
- int min = i; //临时变量
- if( i <= n / 2 ) //如果i是叶节点就不用进行调整
- {
- if( lc <= n && data[lc] > data[min] )
- {
- min = lc;
- }
- if( rc <= n && data[rc] > data[min] )
- {
- min = rc;
- }
- if( min != i )
- {
- swap(&data[i],&data[min]);
- adjust_heap(data,min,n); //避免调整之后以min为父节点的子树不是堆
- }
- }
- }
- void build_heap(int *data,int n) //建立堆
- {
- int i;
- for( i = n / 2; i >= 1; i-- ) //非叶节点最大序号值为n/2
- {
- adjust_heap(data,i,n);
- }
- }
- void sort_heap(int *data,int n) //堆排序
- {
- int i;
- for( i = n; i >= 1; i-- )
- {
- swap(&data[1],&data[i]); //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面
- adjust_heap(data,1,i-1); //重新调整堆顶节点成为大顶堆
- }
- }
- int main(int argc, char *argv[])
- {
- int data[200000];
- int n, k;
- int i;
- while( scanf("%d%d",&n, &k) != EOF )
- {
- for( i = 1; i <= n; i++ ) // 注意此处从 idx = 1 开始
- {
- scanf("%d", &data[i]);
- }
- build_heap(data,n);
- sort_heap(data,n);
- /*
- for( i = 1; i <= n; i++ )
- {
- printf("%d ", data[i]);
- }
- printf("\n");
- */
- while( k > 1 )
- {
- k--;
- printf("%d ", data[1]);
- data[1] = data[n];
- n--;
- sort_heap(data,n);
- }
- printf("%d\n", data[1]);
- }
- return 0;
- }
样例输出:
1 2 3 4
代码:目前想到两种方法: 快排的改版 和 小堆,可惜最后一个实例 的时候 TLE ,不过可以尝试使用 红黑树 ,没有试过。。。。
快排:
min heap:
貌似红黑可以解决超时,AVL也可以尝试,后期再说。。。。