一.斐波那契数列
写入一个函数,输入一个数字n,求斐波那契数列的第n项,该数列的定义如下:
F(0)=0,F(1)=1
F(N)=F(N-1)+F(N+2),其中N>1
斐波那契数列由0和1开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需取模1e9+7
解决方案:
1.递归法(分治)
原理:把F(N)问题的计算拆分成F(N-1)+F(N-2)子问题的计算递归,并以F(0)和F(1)为终止条件
public int fib(int n){
if(n==0) return 0;
if(n==1) return 1;
return (fib(n-1)+fib(n-2))%1000000007;
}
这种解法从逻辑上没问题,但随着n的增大其时间复杂度O(2^n)会很大。
2.通过题目我们可以想到第二种方法:
设正整数x,y,p 求余符号位%,则有:(x+y)%p=(x%p+y%p)%p
所以有:
F(n)%p=[f(n-1)%p+f(n-2)%p]%p
public int fib(int n){
int a=0;
int b=1;
int sum;
for(int i=0;i<n;i++){
sum=(a+b)%1000000007;
a=b;
b=sum;
}
return a;
}
这个解法的时间复杂度仅为O(n).
二.青蛙跳台阶问题
一只青蛙一次可以调上1级台阶,也可以跳上两级台阶,求该青蛙跳上一个n级台阶总过有多少种跳法。
解法:我们可以分析此问题发现其实也是一个斐波那契数列问题
int test(int n){
int a=1,b=1,sum=0;
for(int i=0;i<n;i++){
sum=a+b;
a=b;
b=sum;
}
return a;
}
三.旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转,输入一个递增排序的数组的一个旋转,输出旋转组的最小元素。
解法:
1.找第一个小于前者的数并返回,特殊情况:只有一个元素,输出,都是排序排列的,输出第一个元素
public int minArray(int[] numbers){
if(numbers.length==1) return number[0];
for(int i=0;i<numbers.length-1;i++){
if(numbers[i+1]<number[i])
return number[i+1];
}
return numbers[0];
}
时间复杂度为N,空间为1
2.二分查找法:本题的本质其实就是找数组中的最小元素,我们可以用二分查找来查找
public int minArray(int[] numbers){
int i=0,j=numbers.length-1;
while(i<j){
int m=(i+j)/2;
if(numbers[m]>numbers[j]) i=m+1;
else if(numbers[m]<numbers[j]) j=m;
else j--;
}
return numbers[i];
}
此方法的时间复杂度位Log2N,空间复杂度为1