/**//********************************************************************
purpose: 微软笔试题
求随机数构成的数组中找到长度大于=3的最长的等差数列 输出等差数列由小到大: 如果没有符合条件的就输出 格式: 输入[1,3,0,5,-1,6] 输出[-1,1,3,5] 要求时间复杂度,空间复杂度尽量小
*********************************************************************/ #include <iostream> #include <set> #include <vector>
using namespace std;
// 归并排序 void Merge(int rOrg[], int rBuf[], int from, int mid, int to) { int i = from; int j = mid + 1; int k = from; while (i <= mid && j <= to) { if (rOrg[i] <= rOrg[j]) rBuf[k++] = rOrg[i++]; else rBuf[k++] = rOrg[j++]; } if (i <= mid) while (i <= mid) rBuf[k++] = rOrg[i++]; else while (j <= to) rBuf[k++] = rOrg[j++]; while(k>from) rOrg[--k] = rBuf[k]; } // 归并排序 void MergeSort(int r[], int rBuf[], int from, int to) { if (from == to) rBuf[from] = r[from]; else { int mid = (from + to) / 2; MergeSort(r, rBuf, from, mid); MergeSort(r, rBuf, mid + 1, to); Merge(rBuf, r, from, mid, to); } } // 二分查找 int BinarySearch(int *r, const int &item, int left, int right) { int middle; while(left <= right) { middle = (left + right)/2; if(r[middle] == item) return middle; else if(r[middle] < item) left = middle + 1; else right = middle - 1; } return -1; }
// 求随机数构成的数组中找到长度大于=3的最长的等差数列 void MaxLenEQDistSubArray(int rOrg[], int len) { if (rOrg == NULL || len < 3) { return; } int *rBuf = new int[len]; // 用于归并排序 MergeSort(rOrg, rBuf, 0, len-1);
int** steps = new int*[len]; int* stepP; int i, j, k, jEnd, left, right=len-1, curDist, curLastItem, curLen=0, maxDist, maxLastItem, maxLen=2;
// 初始化 步数数组 for (i = 0; i < len; i++) { steps[i] = new int[len-i]; stepP = steps[i]; for (int j = len-i-1; j >= 0; j-- ) { stepP[j] = 0; } }
// 开始查找最大等差子数组 // i为等差第一项的位置 j为等差第二项位置 for (i = 0; i < len; i++) { jEnd = len - 1; // 要求的等差数列最小长度为3,等差第二项最大为原数组倒数第二项 stepP = steps[i]; for (j = i + 1; j < jEnd; j++) { if (stepP[j-i-1]) { // ① 此index步长j-i己被前面②计算过 continue; } //stepP[j-i-1]=1; // 可省略,因为不会再访问这个标志 curLastItem = rOrg[j]; curDist = rOrg[j]-rOrg[i]; // 本次等差 left = j; curLen = 2; while ((k=BinarySearch(rOrg, curLastItem+curDist, left+1, right)) != -1) { //是否存在下一等差数 curLen++; curLastItem += curDist; steps[left][k-left-1] = 1; // ② 记录 index为left位置 index步长k-left 的数组己被前面计算过 left = k; } if (curLen > maxLen) { // 记录最大等差数列信息 maxLen = curLen; maxLastItem = curLastItem; maxDist = curDist; } } }
// 输出结果 if (maxLen >= 3) { int start = maxLastItem - maxDist*(maxLen-1); cout<<"max length:"<<maxLen<<endl; cout<<"max sub array: "; while(maxLen--) { cout<<start<<" "; start += maxDist; } cout<<endl; } else { cout<<"no GT 3 length sub array"<<endl; }
delete[] rBuf; delete[] steps; }
void Test_MaxLenEQDistSubArray() { /**///// test MergeSort //const int LEN = 8; //int rOrg[LEN]={10,3,5,1,9,34,54,565},rBuf[LEN]; //MergeSort(rOrg, rBuf, 0, LEN-1); //for (int i = 0; i < LEN; i++) // cout << " " << rOrg[i];
int rOrg[] = {1,3,0,5,-1,6}; //{1,3,0,5,-1,6}; {1,3,7,8,9,10,11,0,5,-1,6}; {1,3,7,8,9,10,11,12,0,5,-1,6}; {1,3,7,8,9,10,11,12,13,0,5,-1,6}; MaxLenEQDistSubArray(rOrg, sizeof(rOrg)/sizeof(rOrg[0]));
{ int rOrg[] = {1,3,7,8,9,10,11,0,5,-1,6}; MaxLenEQDistSubArray(rOrg, sizeof(rOrg)/sizeof(rOrg[0])); } { int rOrg[] = {1,3,7,8,9,10,11,12,0,5,-1,6}; MaxLenEQDistSubArray(rOrg, sizeof(rOrg)/sizeof(rOrg[0])); } { int rOrg[] = {1,3,7,8,9,10,11,12,13,0,5,-1,6}; MaxLenEQDistSubArray(rOrg, sizeof(rOrg)/sizeof(rOrg[0])); }
}
|