一、(leetcode 55)给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
思路:
记录在每个位置上,能到达的最大距离;
代码如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
int index=0;
for(int i=0;i<nums.size();i++){
if(i>index){
return false;
}
else{
index=max(index,i+nums[i]);
}
}
return true;
}
};
二、(leetcode 45)给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
思路:
同上一题,增加一个标记,记录跳跃次数
代码如下:
class Solution {
public:
int jump(vector<int>& nums) {
int index=0,end=0;
int res=0;
for(int i=0;i<nums.size()-1;i++){
index=max(index,i+nums[i]);
if(i==end){
end=index;
res++;
}
}
return res;
}
};
三、(leetcode 1306)这里有一个非负整数数组 arr,你最开始位于该数组的起始下标 start 处。当你位于下标 i 处时,你可以跳到 i + arr[i] 或者 i - arr[i]。
请你判断自己是否能够跳到对应元素值为 0 的 任一 下标处。
注意,不管是什么情况下,你都无法跳到数组之外。
代码如下:
class Solution {
public:
bool dfs(vector<int>&arr,int index){
if(index<0||index>=arr.size()||arr[index]==-1){
return false;
}
if(arr[index]==0){
return true;
}
int step=arr[index];
arr[index]=-1;
return dfs(arr,index+step)||dfs(arr,index-step);
}
bool canReach(vector<int>& arr, int start) {
return dfs(arr,start);
}
};
四、(leetcode 1345)给你一个整数数组 arr ,你一开始在数组的第一个元素处(下标为 0)。
每一步,你可以从下标 i 跳到下标:
i + 1 满足:i + 1 < arr.length
i - 1 满足:i - 1 >= 0
j 满足:arr[i] == arr[j] 且 i != j
请你返回到达数组最后一个元素的下标处所需的 最少操作次数 。
注意:任何时候你都不能跳到数组外面。
代码如下:
class Solution {
public:
int minJumps(vector<int>& arr) {
int n=arr.size();
vector<int>step(n,INT_MAX);
vector<int>visited(n,0);
unordered_map<int,vector<int>>m;
step[n-1]=0;
queue<int>q;
q.push(n-1);
for(int i=0;i<n-1;i++){
m[arr[i]].push_back(i);
}
while(!q.empty()){
int u=q.front();
q.pop();
if(u-1>=0&&!visited[u-1]&&m.find(arr[u-1])!=m.end()){
step[u-1]=min(step[u-1],step[u]+1);
visited[u-1]=1;
q.push(u-1);
}
if(u+1<n&&!visited[u+1]&&m.find(arr[u+1])!=m.end()){
step[u+1]=min(step[u+1],step[u]+1);
visited[u+1]=1;
q.push(u+1);
}
if(m.find(arr[u])!=m.end()){
for(int v:m[arr[u]]){
if(!visited[v]){
step[v]=min(step[v],step[u]+1);
visited[v]=1;
q.push(v);
}
}
m.erase(arr[u]);
}
}
return step[0];
}
};
五、(leetcode 1340)给你一个整数数组 arr 和一个整数 d 。每一步你可以从下标 i 跳到:
i + x ,其中 i + x < arr.length 且 0 < x <= d 。
i - x ,其中 i - x >= 0 且 0 < x <= d 。
除此以外,你从下标 i 跳到下标 j 需要满足:arr[i] > arr[j] 且 arr[i] > arr[k] ,其中下标 k 是所有 i 到 j 之间的数字(更正式的,min(i, j) < k < max(i, j))。
你可以选择数组的任意下标开始跳跃。请你返回你 最多 可以访问多少个下标。
请注意,任何时刻你都不能跳到数组的外面。
代码如下:
class Solution {
vector<int>cnt;
public:
void dfs(vector<int>&arr,int idx,int d,int n){
if(cnt[idx]!=-1){
return;
}
cnt[idx]=1;
for(int i=idx-1;i>=0&&i>=idx-d&&arr[idx]>arr[i];i--){
dfs(arr,i,d,n);
cnt[idx]=max(cnt[idx],cnt[i]+1);
}
for(int i=idx+1;i<n&&i<=idx+d&&arr[idx]>arr[i];i++){
dfs(arr,i,d,n);
cnt[idx]=max(cnt[idx],cnt[i]+1);
}
}
int maxJumps(vector<int>& arr, int d) {
int n=arr.size();
cnt.resize(n,-1);
for(int i=0;i<n;i++){
dfs(arr,i,d,n);
}
return *max_element(cnt.begin(),cnt.end());
}
};
六、(leetcode 1696) 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。
一开始你在下标 0 处。每一步,你最多可以往前跳 k 步,但你不能跳出数组的边界。也就是说,你可以从下标 i 跳到 [i + 1, min(n - 1, i + k)] 包含 两个端点的任意位置。
你的目标是到达数组最后一个位置(下标为 n - 1 ),你的 得分 为经过的所有数字之和。
请你返回你能得到的 最大得分 。
思路:
单调栈
代码如下:
class Solution {
public:
int maxResult(vector<int>& nums, int k) {
if(nums.size()==1) return nums[0];
deque<pair<int,int>>q;
q.push_back({nums[0],0});
int res=0;
for(int i=1;i<nums.size();i++){
if(!q.empty()&&i-q.front().second>k){//判断是否过期
q.pop_front();
}
res=q.front().first+nums[i];
while(!q.empty()&&q.back().first<=res){//保持单调减
q.pop_back();
}
q.push_back({res,i});//加入新元素
}
return res;
}
};