考虑由以下规则生成的字符串:
- F[0] =“A”
- F[1] =“B”
- ...
- F[n] = F[n-1] + F[n-2],其中n〉1
给定两个正整数n和k,让我们计算字符串F[n]的前k个位置中字符'B'的个数。
我想出了这个主意,但得到了超出时间限制的错误:
public class Solution {
public static long[] F = new long[50];
public static Scanner input = new Scanner(System.in);
public static long count(int n, long k) {
if (n == 0 || k == 0) return 0;
else if (n == 1) return 1;
else {
if (k > F[n - 1]) return count(n - 1, F[n - 1]) + count(n - 2, k - F[n - 1]);
else return count(n - 1, k);
}
}
public static void main(String[] args) {
F[0] = 1; F[1] = 1;
for (int i = 2; i < 46; i++) F[i] = F[i - 2] + F[i - 1];
int T = input.nextInt();
while (T-- > 0) {
int n = input.nextInt();
long k = input.nextLong();
System.out.println(count(n, k));
}
}
}
时间复杂度O(n^2),时间复杂度O(n^2)。
此问题的测试案例:
| 输入|产出|
| - ------|- ------|
| 四个||
| 0 1|无|
| 十一|1个|
| 3个2|1个|
| 七|四个|
2条答案
按热度按时间mrfwxfqh1#
斐波那契数列似乎有一个规律:
设
g(l, r, k)
表示Fib[n] = l + r
的前k
个位置中B
s的计数,则:上面的答案可能误解了串联的起始顺序,它可能应该是
BA
,在这种情况下,我们需要颠倒l, r
。一个二个一个一个
j7dteeu82#
为清楚起见,将
Fib(n)
定义为斐波那契数列,其中Fib(0) = Fib(1) = 1
和Fib(n+2) = Fib(n+1) + Fib(n)
。注意,
F[n]
有Fib(n)
个字符,其中Fib(n-1)
是B
s。令
C(n, k)
为F[n]
的前k
个字符中的B
的数目。基本情况是显而易见的
一般而言:
这是观察到
F[n] = F[n-1] + F[n-2]
和k
位于第一部分或第二部分中,第一部分具有Fib(n-1)
字符,其中Fib(n-2)
是B
的字符。如果你预先计算了从
0
到n
的斐波那契数列,那么你可以用O(n
)的算术运算来计算C(n, k)
。你标记了java,但这里有一个包含测试用例的python解决方案:
这包括减少
n
的优化,使得最初k > Fib(n-1)
。这使得代码的算术运算为O(min(n, log(k))
)。