2769. 找出最大的可达成数字
2770. 达到末尾下标所需的最大跳跃次数
2771. 构造最长非递减子数组
2772. 使数组中的所有元素都等于零
这题就是简单的不能在简单的简单题, 题目意思是:给你一个数num和操作数t,需要你在对num和x进行t次操作之后,使得x<=num,问这个初始x的最大值是多少?那很显然num不断+1,x不断-1,最后x==num这种情况下,x的初始值最大,代码如下
int theMaximumAchievableX(int num, int t){
return num+2*t;
}
遇到这种从数组头跳到尾的跳跃问题,一般都是用动态规划,但是我们先不用动态规划,我们先用递归来想一想
1.确定递归参数及其返回值:根据题目,它要求从0到n的最大跳跃次数,我们就定义dfs(i)返回从0到i的最大跳跃次数(i表示下标)
2.确定递归的表达式:dfs(i)=max{dfs(k,i)+1} (k
3.确定递归的边界边界和递归入口:
递归边界:i==0时,返回0,即理解为在一开始的跳跃次数是0,或者从0到0不需要跳跃
递归入口:dfs(n-1)
代码如下
//这个是一般的递归写法,会超时
int T;
int*Nums;
int dfs(int i){
if(i==0)
return 0;
int res=INT_MIN;//这里给整形的最小值表示一种不可能的可能性,且不防止后面取较大值
for(int k=0;k
那么如果我们一开始就知道用动态规划,我们应该怎么思考这道题?其实思考的过程和上面的递归神似,我们只要思考下面的三个问题:1.动规的数组的含义是什么?2.动规的递推表达式是什么?3.动规数组的初始化是什么?
参开上面代码我们不难回答上面三个问题:
1.f[i] 代表从0到i所需的最大跳跃次数
2.f[i] = max{ f[k] + 1 } ( k < i ) 条件为abs( f[i] - f[k] ) <= target
3.f[0] = 0
代码就是上面的由递归翻译出的递推
大家可以自己去感悟感悟两种思考过程的联系和区别,对以后的做题还是很有帮助的
其实这题和上面一题一样用递归来解决,我们还是需要(从后往前推)
1.确定递归的参数和返回值:我们需要确定第i个数字取nums1[i]还是nums2[i],所以我们需要两个参数,dfs(i,0/1),i代表当前位下标,0/1代表第i个数选的是哪个数组中的数,返回值代表子数组的最大长度
2.确定递归的表达式:dfs(i,0/1)=max{dfs(i-1,0/1)+1} 前提:符合条件
3.递归的边界和入口:边界条件:i==0,返回1
代码如下
int **nums;
int*Nums1;
int*Nums2;
int**memo;
int dfs(int i,int j){
if(i==0)
return 1;
if(memo[i][j]!=-1)
return memo[i][j];
int res=1;
if(Nums1[i-1]<=nums[j][i])
res=fmax(res,dfs(i-1,0)+1);
if(Nums2[i-1]<=nums[j][i])
res=fmax(res,dfs(i-1,1)+1);
return memo[i][j]=res;
}
int maxNonDecreasingLength(int* nums1, int nums1Size, int* nums2, int nums2Size){
nums=(int**)malloc(sizeof(int*)*2);
nums[0]=nums1,nums[1]=nums2;
Nums1=nums1,Nums2=nums2;
memo=(int**)malloc(sizeof(int*)*nums1Size);
for(int i=0;i
这题看到对一段区间进行加减的操作就要想到差分数组,那么差分数组是啥?下面举个例子来带领大家了解一下
了解了差分数组之后,这题其实就迎刃而解了,补充一点当差分数组全为0时,原数组就是全0
代码如下
bool checkArray(int* nums, int numsSize, int k){
int f[numsSize+1];//防止x下面的i+k越界
memset(f,0,sizeof(f));
f[0]=nums[0];
for(int i=1;i0){
f[i+k]+=f[i];
f[i]=0;
}
}
for(int i=0;i<=numsSize;i++){
if(f[i]!=0)
return false;
}
return true;
}