[微软][笔试] 找出最大序列对

对于一个数组,找出这样一个序列对(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 }
posted @ 2012-11-07 22:53  chkkch  阅读(489)  评论(0编辑  收藏  举报