codility上的问题之十 iota 2011

时间:2023-01-08 00:01:38

又是描述较长的一个题。题目本身就是说给定一个数组A,如果两个数在A中相邻出现,就叫做这两个数在A中相邻相邻。数组B和数组A相邻,如果同时满足

(1) B[0] = A[0]

  (2)  B[M - 1] = A[N - 1]  M, N分别是B和A的长度

(3) B中相邻的两个数在A中也相邻


求出一个和数组A相邻的数组B最短的长度。

数据范围:

N 1..10^5

每个数的范围 整数[-2147483648..+2147483647]

要求复杂度:时间O(NlogN),空间O(N)


分析: 首先数组B肯定存在,因为可以让B=A。我们可以按照相邻关系建立一个无向图。如果两个数在A种相邻,则这两个数有条边。所以节点数是O(N),变数是 O(2N) = O(N)。

然后B的长度其实就是从A[0]到A[N-1]最短路的长度,bfs就行。。。。logN的原因是我们要用map,因为数据范围不能直接放到下标里……还要注意B可以直有一个元素的。如果A[0] == A[N - 1],那么取B[0] = A[0],长度为1满足条件。

代码:

// you can also use includes, for example:
// #include <algorithm>
#include <set>
#include <map>
#include <queue>

int solution(const vector<int> &A) {
// write your code here...
int n = A.size(),i,x,y;
if (A[0] == A[n - 1]) {
return 1;
}
map<int, set<int> > e;
map<int,int> d;
for (i = 1; i < n; ++i) {
e[A[i]].insert(A[i - 1]);
e[A[i - 1]].insert(A[i]);
}
map<int,set<int> >::iterator t;
set<int>::iterator it;
map<int,int>::iterator tt;
queue<int> q;
d[A[0]] = 1;
for (q.push(A[0]);;q.pop()) {
x = q.front();
t = e.find(x);
if (t != e.end()) {
y = d[x] + 1;
for (it = t->second.begin(); it != t->second.end(); ++it) {
if (*it == A[n - 1]) {
return y;
}
tt = d.find(*it);
if (tt == d.end()) {
if (*it == A[n - 1]) {
return y;
}
d.insert(make_pair(*it, y));
q.push(*it);
}
}
}
}
return y;


}