codility上的问题之十 iota 2011

又是描述较长的一个题。题目本身就是说给定一个数组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;   
    
        
}



你可能感兴趣的:(codility)