算法题:两数组所有和值的最小前 k 项
来源:互联网 发布:安卓mac地址修改器 编辑:程序博客网 时间:2024/05/16 14:43
问题:有两个单调递增的数组 a[n] 和 b[m],这两个数组的和值 a[i]+b[j],其中 i=1, ..., n,j=1, ..., m,共有 n*m 个,要求返回前 k 项最小的和。例如:a[4] = {-5, 2, 7, 14},b[4]={-3, -1, 15, 21} 时,要求返回前 8 个时为:-8, -6, -1, 1, 4, 6, 10, 11。
具体的程序如下:
#include <stdio.h>#include <stdlib.h>#define max(a,b) ((a)>=(b) ? (a) : (b))int a[4] = {-5, 2, 7, 14};int b[4] = {-3, -1, 15, 21};int n = sizeof(a)/sizeof(a[0]); //数组a的长度int m = sizeof(b)/sizeof(b[0]); //数组b的长度struct point {int x;int y;};int ptcmp(struct point pt1, struct point pt2){return a[pt1.x]+b[pt1.y]-a[pt2.x]-b[pt2.y];}void minheapify(struct point *arr, int i, int len){int least, l, r;struct point temppt;l = 2*i + 1;r = 2*i + 2;if (len>1) {if (l < len && ptcmp(arr[l], arr[i]) < 0)least = l;elseleast = i;if (r < len && ptcmp(arr[r], arr[least]) < 0)least = r;if (least != i) {temppt = arr[i];arr[i] = arr[least];arr[least] = temppt;minheapify(arr, least, len);}}}struct point heapexactmin(struct point *arr,int *lenpt){struct point temppt;if (*lenpt < 1) {printf("heap underflow\n");exit(1);}//交换数组的第一个元素和最后一个元素temppt = arr[0];arr[0] = arr[*lenpt-1];arr[*lenpt-1] = temppt;*lenpt = *lenpt - 1;//保持最小堆minheapify(arr, 0, *lenpt);return arr[*lenpt];}void heapinsert(struct point *arr, int *lenpt, struct point newpt){int i;struct point temppt;arr[*lenpt] = newpt;*lenpt = *lenpt + 1;i = *lenpt - 1;while ((i-1)/2 >= 0 && ptcmp(arr[i], arr[(i-1)/2]) < 0) {temppt = arr[i];arr[i] = arr[(i-1)/2];arr[(i-1)/2] = temppt;i = (i-1)/2;}}int main(){int candnum;struct point *cand;struct point minpt, rpt, dpt;int i, count, k;int *kminsum;printf("Please enter a positive integer number no more than %d for variable k:\n", m*n);scanf("%d", &k);kminsum = (int *) malloc(k*sizeof(int));cand = (struct point *) malloc(max(n,m)*sizeof(struct point));//初始化 cand 数组cand[0].x = 0;cand[0].y = 0;candnum = 1;count = 0;while (count < k) {minpt = heapexactmin(cand, &candnum);kminsum[count] = a[minpt.x] + b[minpt.y];//判断 minpt 右边的点能否加进 cand 数组rpt.x = minpt.x;rpt.y = minpt.y+1;if (rpt.y < m) {for (i=0; i<candnum && (rpt.x != cand[i].x || rpt.y != cand[i].y); i++);if (i >= candnum)heapinsert(cand, &candnum, rpt);}//判断 minpt 下边的点能否加进 cand 数组dpt.x = minpt.x+1;dpt.y = minpt.y;if (dpt.x < n) {for (i=0; i<candnum && (dpt.x != cand[i].x || dpt.y != cand[i].y); i++);if (i >= candnum)heapinsert(cand, &candnum, dpt);}count++;}for (count = 0; count < k; count++)printf("%d ", kminsum[count]);printf("%\n");return 0;}
注:在这里我用到了堆的相关操作,其实是不必要的。只不过是我想练习一下堆的相关操作而已。从 main 函数中可以看出算法的思想很简单。但是我本人对这个算法不是很满意,希望能找到更好的算法。
- 算法题:两数组所有和值的最小前 k 项
- 算法-求两个有序数组两两相加的值最小的K个数
- 找出数组中前K小的值&最小堆
- 两有序数组两两之和的最小k个值, 最小堆解法之完整版
- 输入一个整数数组,返回所有元素两两之差绝对值最小的值,O(n)算法
- 面试题精选(78):输出两有序数组和的前k项(O(klgk)复杂度)
- 算法题:求数组中最小的k个数
- 找出无序数组中最小的前k个数
- 找出无序数组中最小的前k个数
- 求一数组前k大的所有数
- UVA 11997 K Smallest Sums(多路归并求前k个最小和的值)
- 两个有序数组,A[k]和B[k]长度都为k。求前k个最小的(a[i]+b[j])
- 微软面试题:求两升序排序数组两两数字之和中,最小的k个值
- 最小的前k个数
- 【面试题】求两个有序数组两两相加的值最小的K个数
- 求两个有序数组两两相加的值最小的K个数
- 求两个有序数组两两相加的值最小的K个数
- 面试常考算法题 局部最小 求二叉树结点 求两个数组中所有数的上中位数 两个数组的所有数中第K小的数
- 原码反码补码
- AspectJ的Execution表达式
- java.sql.Date与java.util.Date的区别
- 要学习的知识—做个笔记方便查找
- phpcms搬站需要修改的地方,避免拉下
- 算法题:两数组所有和值的最小前 k 项
- WindowsPhone中的ScrollableTextBlock
- 利用python包(xlrd和xlwt)处理excel
- C++作业03_02: 下楼问题。从楼上走到楼下共有h个台阶,每一步有三种走法
- windows上用libnfc的库函数编程
- new一个类对象和使用类名创建一个对象有什么区别?
- Android SurfaceFlinger对VSync信号的处理过程分析
- C++函数的返回值——返回引用类型&非引用类型
- Installation error: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED 错误