@rg070836rg
2015-11-01T14:17:02.000000Z
字数 2708
阅读 1751
算法概论作业
给定两个有序表,大小分别为m和n。给出一个算法,以
O(logm+logn) 的时间找出两个列表合并后的有序列表中的第K小元素
我们从最基础的情况开始考虑,假设一个数组为空,在另一个数组中找第K小元素,很明显,如果k不超过第二个数组的长度,那么结果就是B[bLeft+k-1]
反之同理
所以,合法性判定,和终止判定如下
if (k>(aRight - aLeft + 1 + bRight - bLeft + 1)){cerr << "输入不合法" << endl;return -1;}if (aLeft > aRight){return B[bLeft+ k - 1];}if (bLeft> bRight){return A[aLeft+ k - 1];}
下面,我们回归一般情况下
我们取
int aMiddle = (aLeft + aRight) / 2;int bMiddle = (bLeft + bRight) / 2;
首先比较
我们不妨假设
如果满足
那么必定有
A[aMiddle+1,...,aRight] 排在所有元素的(aMiddle+bMiddle) 之后
同时还有B[bLeft,...,bMiddle] 排在所有元素的(aMiddle+bMiddle) 之前
然后那么如果
k <= (aMiddle-aLeft)+(bMiddle-bLeft)+1
我们可以把A数组右边的部分舍弃,否则
我们可以把B数组的左边部分舍弃,并在剩余部分寻找第(k-舍弃部分的个数)
反之亦然。
代码如下
if (A[aMiddle] > B[bMiddle]){if (k <= (aMiddle - aLeft) + (bMiddle - bLeft) + 1)FindElement(A, B, aLeft, aMiddle - 1, bLeft, bRight, k);elseFindElement(A, B, aLeft, aRight, bMiddle + 1, bRight, k - (bMiddle - bLeft) - 1);}else{if (k <= ((aMiddle - aLeft) + (bMiddle - bLeft) + 1))FindElement(A, B, aLeft, aRight, bLeft, bMiddle - 1, k);elseFindElement(A, B, aMiddle + 1, aRight, bLeft, bRight, k - (aMiddle - aLeft) - 1);}
全部代码如下:
#include<iostream>using namespace std;int FindElement(int A[], int B[], int aLeft, int aRight, int bLeft, int bRight, int k);int main(){int A[10] = { 1, 3, 5, 6, 7, 9, 11, 13, 15, 17 };int B[5] = { 2, 4, 8, 10, 12, };//int k;//cout << "请输入k的值:";//cin >> k;for (int k = 1; k < 10; k++)cout << endl << FindElement(A, B, 0, 9, 0, 4, k);return 0;}int FindElement(int A[], int B[], int aLeft, int aRight, int bLeft, int bRight, int k){if (k > (aRight - aLeft + 1 + bRight - bLeft + 1)){cerr << "输入不合法" << endl;return -1;}if (aLeft > aRight){return B[bLeft + k - 1];}if (bLeft > bRight){return A[aLeft + k - 1];}int aMiddle = (aLeft + aRight) / 2;int bMiddle = (bLeft + bRight) / 2;if (A[aMiddle] > B[bMiddle]){if (k <= (aMiddle - aLeft) + (bMiddle - bLeft) + 1)FindElement(A, B, aLeft, aMiddle - 1, bLeft, bRight, k);elseFindElement(A, B, aLeft, aRight, bMiddle + 1, bRight, k - (bMiddle - bLeft + 1));}else{if (k <= ((aMiddle - aLeft) + (bMiddle - bLeft) + 1))FindElement(A, B, aLeft, aRight, bLeft, bMiddle - 1, k);elseFindElement(A, B, aMiddle + 1, aRight, bLeft, bRight, k - (aMiddle - aLeft + 1));}}
(a)
b)
因为分治之后得到的子问题不再是平方操作了,所以该算法的运行时间不是
算法:
int gcd(int a, int b){if(a == 0) return b;if(b == 0) return a;if(a % 2 == 0 && b % 2 == 0) return 2 * gcd(a/2, b/2);else if(a % 2 == 0) return gcd(a/2 , b);else if(b % 2 == 0) return gcd(a, b/2);else return gcd(abs(a - b), Min(a, b));}int Min(int a,int b){if (a >= b){return b;}elsereturn a;}
