上一篇:https://blog.csdn.net/qq_41345173/article/details/104235084
1. 跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
int jumpFloor(int number) {
int pre=0, next=1, now=0;
while(number--){
now=pre+next;
pre=next;
next=now;
}
return now;
}
2. 变态跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
int jumpFloorII(int number) {
int res=1;
while(number>1){
res *=2;
number--;
}
return res;
}
注意:此时有数学归纳法可知f(n)=2^(n-1)种跳法
3. 矩形覆盖
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
int rectCover(int number) {
int pre = 0, next = 1, now = 0;
while(number--){
now = pre+next;
pre = next;
next = now;
}
return now;
}
和第一题跳台阶一个道理,当n=1时右一种方法,n=2时有两种方法,当n=n时,若选择竖着放相当于f(n-1)的方法,若横着放相当于f(n-2)的放法。故这是一个不完全符合斐波那契数列的数列
4. 矩阵中的路径
题目链接: https://www.nowcoder.com/practice/
class Solution {
public:
bool hasPathCore(char* matrix, int rows, int cols,int row,int col,char* str,int &pathLength,bool *visited){
if(str[pathLength]=='\0')
return true;
bool hasPath = false;
if(row>=0&&row<rows&&col>=0&&col<cols&&matrix[row*cols+col]==str[pathLength]&&!visited[row*cols+col]){
++pathLength;
visited[row*cols+col] = true;
hasPath = hasPathCore(matrix,rows,cols,row,col-1,str,pathLength,visited)||
hasPathCore(matrix,rows,cols,row,col+1,str,pathLength,visited)||
hasPathCore(matrix,rows,cols,row-1,col,str,pathLength,visited)||
hasPathCore(matrix,rows,cols,row+1,col,str,pathLength,visited);
if(!hasPath){
--pathLength;
visited[row*cols+col] = false;
}
}
return hasPath;
}
bool hasPath(char* matrix, int rows, int cols, char* str)
{
if(matrix==nullptr||rows<1||cols<1||str==nullptr)
return false;
int len = rows*cols, i;
bool *visited = new bool[len];
memset(visited,0,len);
int pathLength = 0;
for(int row=0;row<rows;++row){
for(int col=0;col<cols;++col){
if(hasPathCore(matrix,rows,cols,row,col,str,pathLength,visited)){
return true;
}
}
}
delete []visited;
return false;
}
};
回溯法的典型应用,显然递归要比迭代编码方便的多。
5. 机器人的运动范围
地上有一个m行和n列的方格。一个机器人从座标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行座标和列座标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
class Solution {
public:
int getDigitSum(int number){
int sum=0;
while(number>0){
sum +=number%10;
number /=10;
}
return sum;
}
bool check(int threshold, int rows, int cols, int row, int col, bool *visited){
if(row>=0&&row<rows&&col>=0&&col<cols&&getDigitSum(row)+getDigitSum(col)<=threshold&&!visited[row*cols+col])
return true;
return false;
}
int movingCountCore(int threshold, int rows, int cols, int row, int col, bool *visited){
int count=0;
if(check(threshold,rows,cols,row,col,visited)){
visited[row*cols+col] = true;
count =1+ movingCountCore(threshold,rows,cols,row-1,col,visited)+
movingCountCore(threshold,rows,cols,row+1,col,visited)+
movingCountCore(threshold,rows,cols,row,col-1,visited)+
movingCountCore(threshold,rows,cols,row,col+1,visited);
}
return count;
}
int movingCount(int threshold, int rows, int cols)
{
if(threshold<0||rows<=0||cols<=0)
return 0;
int len = rows*cols;
bool *visited = new bool[len];
memset(visited,0,len);
int count = movingCountCore(threshold,rows,cols,0,0,visited);
delete []visited;
return count;
}
};
和上一题一样也是回溯法的典型应用,重点是破题,出发点为起始点,然后 对每一个周边点做判断是否可行,若可行继续判断周边值的周边值之和,经过层层递归可得最终结果。
6.剪绳子
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]xk[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
class Solution {
public:
int cutRope(int number) {
if(number<2)
return 0;
if(number==2)
return 1;
if(number==3)
return 2;
int product[number];
product[0]=0,product[1]=1,product[2]=2,product[3]=3;
int max;
for(int i=4;i<=number;++i){
max = 0;
for(int j=1;j<=i/2;++j){
int mid = product[j]*product[i-j];
if(mid>max)
max = mid;
}
product[i] = max;
}
return max;
}
};
动态规划的巧妙应用,还有一种贪心算法,高明的设计思路,需要推导