Codility上的练习(11)
来源:互联网 发布:植物大战僵尸2for mac 编辑:程序博客网 时间:2024/06/15 08:04
(1)Ladder
给定两个等长的数组A和B, A[i]和B[i]表示求一个有A[i]级的梯子,每次上1级或者两级,上到最高级的方法数对2^B[i]取余数的结果。
数据范围:数组长度 L [1..30000] , A中数字范围 [1..L], B中数字范围[1..30]
要求复杂度 时间空间都是O(L)
分析:打表法——我们循环可以把0..L的结果都算出来 f[i] = f[i - 1] + f[i - 2] , f[0] = f[1] = 1。 关键点在于取余数,这个取余数很特殊,对2^B[i]取余数,相当于取结果的低B[i] bit。因此我们可以取所有结果的低30位,打好表,输出时再真正取B[i]位,就能达到O(L)的复杂度了。
// you can also use includes, for example:// #include <algorithm>const int M = (1 << 30) - 1;vector<int> solution(vector<int> &A, vector<int> &B) { // write your code in C++98 int m = 0; for (int i = 0; i < A.size(); ++i) { m = max(m, A[i]); } vector<int> f; f.resize(m + 1); f[0] = f[1] = 1; for (int i = 2; i <= m; ++i) { f[i] = (f[i - 1] + f[i - 2]) & M; } vector<int> answer; for (int i = 0; i < A.size(); ++i) { answer.push_back(f[A[i]] & ((1 << B[i]) - 1)); } return answer;}
(2) FibFrog
先给了Fibonacci的定义F[0] = 0, F[1] = 1, F(M) = F(M - 1) + F(M - 2) if M >= 2。一只青蛙想从河岸(-1)跳到对岸(N)。中间有0..N-1这N个位置,有一个数组A[]表示这些位置是否有荷叶 ,0表示没有,1表示有。青蛙从岸上要跳到荷叶上,通过0个或者多个荷叶跳到对岸,而且只能朝对岸的方向跳——不能往回跳。而且青蛙每次跳的距离必须是一个Fibonacci数,请问青蛙最少几步跳到对岸?无解返回-1。
数据范围: N [0..30000]
要求复杂度 :时间O(NlogN),空间O(N)。
分析: 首先我们可以把数组尾端加一个1,表示对岸。可以认为首端有一个1或者认为数组下标从1开始,我们现在目标是到数组最后一个元素,只能通过1且跳的距离是Fibonacci数的最小步数。 这是一个显然的dp (或者说是bfs)。对于位置i 并且A[i] == 1,我们有 dp[i] = min(dp[i - f[j]]) + 1 其中f[j]是fibonacci数并且满足A[i - f[j]]==1
因为Fibonacci是指数增长的,所以不超过N的Fibonacci数是O(logN)个,整个递推的时间复杂度是O(NlogN)。
// you can also use includes, for example:// #include <algorithm>int solution(vector<int> &A) { // write your code in C++98 A.push_back(1); int n = A.size(); vector<int> f; f.push_back(1); f.push_back(1); for (int i = 1; f[i] < n; ++i) { f.push_back(f[i] + f[i - 1]); } vector<int> answer; answer.resize(n + 1, -1); answer[0] = 0; for (int i = 1; i <= n; ++i) { answer[i] = -1; if (A[i - 1] == 0) { continue; } for (int j = 0;(j < f.size()) && (i >= f[j]); ++j) { if ((answer[i - f[j]] >= 0) && ((answer[i] < 0) || (answer[i] > answer[i - f[j]] + 1))) { answer[i] = answer[i - f[j]] + 1; } } } return answer[n];}
- Codility上的练习(11)
- codility上的练习 (1)
- codility上的练习(2)
- codility上的练习(3)
- codility上的练习(5)
- Codility上的练习 (9)
- Codility上的练习(12)
- Codility上的练习 (13)
- Codility上的练习 (14)
- codility上的练习 (4)
- Codility上的练习 (6)
- codility上的练习(7)
- codility上的练习(8)
- Codility上的练习 (10)
- Codility上的练习 (15)
- codility上的问题 11 Kappa 2011
- codility上的一道题
- 一个Codility上的练习遇到和预期结果不同的问题。
- 托盘图标在explorer.exe进程退出重启后图标消失(应用程序进程依然存在)的问题
- docx4j学习笔记(4)
- JAVA使用循环和递归方法实现斐波拉切数列
- express 与 mvc
- iOS框架
- Codility上的练习(11)
- 初识GitHub
- Linux程序自启动设置方法
- 人工智能杂谈
- POJ 1062题解 Dijkstra
- 统计字母频率并排序
- POJ 1600 Centipede Collisions
- ArrayAdapter和SimpleAdapter简单使用
- Codeforces Round #277.5 (Div. 2) C Given Length and Sum of Digits...