[微软][笔试] 找出最大序列对
对于一个数组,找出这样一个序列对(i, j),满足A[i] < A[j],且使 j - i的值最大,输出j - i的值。
这道题最初想到的是O(n^2)的解答,后来想到了用MergeSort时来记录最大序列对的方法,也可以用一个队列来做。总之解法还挺多。
最后和http://ac.jobdu.com/problem.php?cid=1039&pid=19何海涛的这题非常相似。
方法1:MergeSort,数组的元素需要记录原始的元素索引。
1 #include <iostream> 2 using namespace std; 3 4 struct Node 5 { 6 int val; 7 int index; 8 }; 9 Node b[1000]; 10 11 int mergeSort(Node a[], int left, int right) 12 { 13 if (left > right) 14 return -1; 15 16 if (left == right) 17 return 0; 18 19 int mid = left + (right - left) / 2; 20 21 int leftRes = mergeSort(a, left, mid); 22 int rightRes = mergeSort(a, mid + 1, right); 23 24 int res = max(leftRes, rightRes); 25 26 int i = left; 27 int j = mid + 1; 28 int minIndex = INT_MAX; 29 int index = i; 30 31 while(i <= mid && j <= right) 32 { 33 if (a[i].val <= a[j].val) 34 b[index] = a[i++]; 35 else 36 b[index] = a[j++]; 37 38 if (minIndex != INT_MAX) 39 res = max(b[index].index - minIndex, res); 40 41 minIndex = min(b[index].index, minIndex); 42 43 index++; 44 } 45 46 while(i <= mid) 47 { 48 b[index] = a[i++]; 49 50 if (minIndex != INT_MAX) 51 res = max(b[index].index - minIndex, res); 52 53 minIndex = min(b[index].index, minIndex); 54 55 index++; 56 } 57 58 while(j <= right) 59 { 60 b[index] = a[j++]; 61 62 if (minIndex != INT_MAX) 63 res = max(b[index].index - minIndex, res); 64 65 minIndex = min(b[index].index, minIndex); 66 67 index++; 68 } 69 70 return res; 71 } 72 73 int main() 74 { 75 int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 76 77 int aSize = sizeof(a) / sizeof(int); 78 79 Node *c = new Node[aSize]; 80 81 for(int i = 0; i < aSize; i++) 82 { 83 c[i].val = a[i]; 84 c[i].index = i; 85 } 86 87 cout << mergeSort(c, 0, aSize - 1) << endl; 88 }
方法2:用一个队列保存递减序列,从数组的第一个数开始,不断放入,当当前数小于队列的尾元素则放入。这样就构成了一个递减序列。当有新元素时查找队列中第一个小于新元素的数,然后就能得出一个j-i的值,如此就能得出解。由于队列有序,所以用二分查找的变形O(logn)。最后总的复杂度O(nlogn)
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 struct Node 6 { 7 int index; 8 int val; 9 Node(){} 10 Node(int idx, int v):index(idx), val(v){} 11 }; 12 13 int findIndex(vector<Node> &a, int left, int right, int key) 14 { 15 if (left > right) 16 return -1; 17 18 int mid = left + (right - left) / 2; 19 20 if (a[mid].val < key) 21 { 22 int index = findIndex(a, left, mid - 1, key); 23 return (index == -1 ? a[mid].index : index); 24 } 25 else 26 { 27 return findIndex(a, mid + 1, right, key); 28 } 29 } 30 31 int solve(int a[], int aSize) 32 { 33 if (aSize == 0) 34 return 0; 35 36 vector<Node> q; 37 38 int res = 0; 39 for(int i = 0; i < aSize; i++) 40 { 41 if (q.size() == 0) 42 q.push_back(Node(i, a[i])); 43 else if (q[q.size() - 1].val > a[i]) 44 q.push_back(Node(i, a[i])); 45 46 int index = findIndex(q, 0, q.size() - 1, a[i]); 47 48 if (index != -1) 49 res = max(res, i - index); 50 } 51 52 return res; 53 } 54 55 int main() 56 { 57 int a[] = {9, 8, 7, 6, 5, 4, 3, 2, 9}; 58 int aSize = sizeof(a) / sizeof(int); 59 cout << solve(a, aSize) << endl; 60 61 int b[] = {1, 2, 3}; 62 int bSize = sizeof(b) / sizeof(int); 63 cout << solve(b, bSize) << endl; 64 65 int c[] = {3, 2, 1}; 66 int cSize = sizeof(c) / sizeof(int); 67 cout << solve(c, cSize) << endl; 68 }