codility上的練習 (1)


codility上面添加了教程。目前只有lesson 1,講復雜度的……里面有幾個題, 目前感覺題庫的題簡單。

tasks:

Frog-Jmp:

一只青蛙,要從X跳到Y或者大於等於Y的地方,每次跳的距離為D,問至少跳幾次。 X,Y,D都是[1..10^9]的整數。

要求時間空間復雜度O(1)。

這個題比較簡單,就是做除法嘛,我們不知道X是否已經不小於Y了,我加了個判斷,不過也就一句話。

代碼:

// you can also use includes, for example:
// #include <algorithm>
int solution(int X, int Y, int D) {
// write your code here...
return (X >= Y)?0:((Y - X + D - 1) / D);
}

Perm-Missing-Elem:

一個長度為N的數組里,都是整數,所有的數都不相同,范圍是[1..N + 1],這意味着有一個整數缺失了,找到這個缺失的整數,N的范圍[0..10^5], 要求時間復雜度O(N),空間復雜度O(1)。

分析:這個題是old題,我們至少有3種方法解決。

1 求和,注意使用long long。

// you can also use includes, for example:
// #include <algorithm>
int solution(vector<int> &A) {
// write your code here...
int n = A.size(), i;
long long r = n + 1;
for (i = 0; i < n; ++i) {
r += (i + 1) - A[i];
}
return r;
}

2 求異或,不需要long long

// you can also use includes, for example:
// #include <algorithm>
int solution(vector<int> &A) {
// write your code here...
int n = A.size(), i, r = n + 1;
for (i = 0; i < n; ++i) {
r ^= (i + 1) ^ A[i];
}
return r;
}

3 把A[i]換到下標為A[i] - 1的位置,注意(N + 1)單獨拿出來

// you can also use includes, for example:
// #include <algorithm>
int solution(vector<int> &A) {
// write your code here...
int n = A.size(),i,x,t;
for (i = 0; i < n; ++i) {
for (x = A[i]; (x <= n) && (A[x - 1] != x); ) {
t = A[x - 1];
A[x - 1] = x;
x = t;
}
}
for (i = 0; i < n; ++i) {
if (A[i] != i + 1) {
break;
}
}
return i + 1;

}

Tape-Equilibrium:

空數組長度為N,定義對0 < P < N, |(A[0] + A[1] + ... + A[P − 1]) − (A[P] + A[P + 1] + ... + A[N − 1])|為P分割的兩部分的差值,求最小的差值。 N在[2..10^5],數組中數據范圍[-1000,+1000]。要求復雜度時間O(N),空間O(N)。

分析:這個題可以做到空間O(1),我們主需要記錄前P項和和總合就可以了。

// you can also use includes, for example:
// #include <algorithm>
int solution(vector<int> &A) {
// write your code here...
int n = A.size(), sum, r, i, t;
for (i = sum = 0; i < n; ++i) {
sum += A[i];
}
r = abs(sum - A[0] - A[0]);
for (i = 2, t = A[0]; i < n; ++i) {
t += A[i - 1];
r = min(r, abs(sum - t - t));
}
return r;
}

Further Training: 

Abs-distinct:

一個長度為N的整數數組,已經按非降序排好序,求數組中的數有多少種不同的絕對值。數據范圍N [1..10^5],數組元素[-2147483648,+2147483647]。

要求復雜度 時間O(N),空間O(N)。

分析:這個題可以做到空間復雜度O(1),因為數組是排好序的,我們可以兩頭掃。但是由於數據范圍-2147483648,我們不能隨便取絕對值,因為會整數越界,這里要小心謹慎,不然過不了某一組數據。

// you can also use includes, for example:
// #include <algorithm>
int solution(const vector<int> &A) {
    // write your code here...
int n = A.size(), i, j ,r, t;
    for (i = r = 0, j = n - 1; (i < j) && (A[i] < 0) && (A[j] > 0); ++r) {
        t = (A[i] + A[j] < 0)?A[i]:A[j];
        for (;((t < 0) && (A[i] == t)) || ((t > 0) && (A[i] + t == 0)) ; ++i);
        for (;((t < 0) && (A[j] + t == 0)) || ((t > 0) && (A[j] == t)); --j);
    }
    for (;i <= j;++r) {
        for (t = A[i]; (i <= j) && (A[i] == t); ++i)
        ;
    }
    return r;
}


Binary-gap:

一個整數的2進制表示中,兩個1bit直接全部是0, 0的個數叫做一個binary-gap,給定N,求其最長binary-gap。(兩個1之間最大的連續0的個數)。

N [1..2147483647]。要求復雜度時間O(logN),空間O(1)。

分析:右移(防止越界),我們記錄上一個1bit的位置就可以了。

// you can also use includes, for example:
// #include <algorithm>
int solution(int N) {
// write your code here...
int i,r, last;
for (i = r = 0, last = -1; N; N >>= 1,++i) {
if (N & 1) {
if (last >= 0) {
r = max(i - last - 1, r);
}
last = i;
}
}
return r;
}

Equi:

貌似跟第一篇codility上的問題是一樣的,只是改版后放到這里來了。

http://blog.csdn.net/caopengcs/article/details/9323743

// you can also use includes, for example:
// #include
int solution(const vector<int> &A) {
// write your code here...
int n = A.size(),i;
long long sum = 0, left = 0;
for (i = 0; i < n; ++i) {
sum += A[i];
}
for (i = 0; i < n; ++i) {
if (left == sum - A[i] - left) {
return i;
}
left += A[i];
}


}


Dominator:

找眾數,即數組中出現次數超過一半的數。數組長度N [0..10^6] (有0),每個數組元素,整數[-2147483648, +2147483647]。要求時間復雜度O(N),空間復雜度O(1)。

返回的是眾數的任意一個下標。沒有眾數返回-1。

分析: 經典算法,假設眾數是x,掃一遍,相同的話加一次,不同的話減一次,次數變為負數就換掉x。最后還要檢查一遍x是否真的為眾數。

代碼:

// you can also use includes, for example:
// #include <algorithm>
int solution(const vector<int> &A) {
// write your code here...
int r, i , t, n = A.size();
for (i = r = t = 0; i < n; ++i) {
if (A[i] == A[r]) {
++t;
}
else if (--t < 0) {
t = 1;
r = i;
}
}
for (i = n - 1, n >>= 1; i >= 0; --i) {
if ((A[i] == A[r]) && (--n < 0)) {
return r;
}
}
return -1;
}

Max-profit:

給定數組是股票價錢,要在早時買,晚些時候賣(可以是同一天),求最大收益。天數N [1..10^5],每天的價格[0..10^9]。要求復雜度時間O(N),空間O(1)。

分析:這個題已經寫入算法導論第三版了,可以轉化為最大子段和。但是還有另外的方法,如果我們知道某天賣出,那么買入的時候一定是這些天最便宜的日子收益才能最大。

代碼:

// you can also use includes, for example:
// #include <algorithm>
int solution(const vector<int> &A) {
// write your code here...
int n = A.size(), i, profit, cheapest;
for (i = profit = cheapest = 0; i < n; ++i) {
if (A[i] < A[cheapest]) {
cheapest = i;
}
profit = max(profit, A[i] - A[cheapest]);
}
return profit;
}


Tree-height:

二叉樹的高度,節點數N [1..1000],要求復雜度時間空間都是O(N)。

分析:就是dfs,至於空間的話,主要看堆棧是否要計算了……代碼我就寫了一句話。

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

int solution(tree * T) {
// write your code here...
return T?(max(solution(T->l),solution(T->r)) + 1):(-1);
}

Array-inversion-count:

就是求數組逆序數,超過10^9,返回-1。 要求時間復雜度O(NlogN),空間復雜度O(N),沒給N的范圍。

經典分治算法,跟歸並排序一樣。

代碼:

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

vector<int> temp;
int help(vector<int> &A,int from,int to) {
int i,j,r,r1,r2,mid;
if (to - from <= 0) {
return 0;
}
mid = (from + to) >> 1;
r1 = help(A, from, mid);
if (r1 > 1000000000) {
return -1;
}
r2 = help(A, mid + 1, to);
if (r2 > 1000000000) {
return -1;
}
if ((r = r1 + r2) > 1000000000) {
return -1;
}
temp.clear();
for (i = from, j = mid + 1; (i <= mid) && (j <= to);) {
if (A[i] <= A[j]) {
temp.push_back(A[i++]);
}
else {
if ((r += mid - i + 1) > 1000000000) {
return -1;
}
temp.push_back(A[j++]);
}
}
for (;i <= mid;++i) {
temp.push_back(A[i]);
}
for (;j <= to; ++j) {
temp.push_back(A[j]);
}
for (i = from; i <= to; ++i) {
A[i] = temp[i - from];
}
return r;
}

int solution(const vector<int> &A) {
// write your code here...
vector<int> a = A;
return help(a, 0, a.size() - 1);
}








 

                        
                        
                 

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com