题目描述
给你一个整数数组 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 {
public:
bool f[1002]={0};
int search(int i, int d,vector<int>& arr)
{
int j=1;
int n=arr.size();
int sum=0;
int ans=0;
while (j<=d && i-j>-1 && arr[i-j]<arr[i])
{
if (!f[i-j])
{
sum=1;
f[i-j]=1;
sum+=search(i-j,d,arr);
if(sum>ans) ans=sum;
f[i-j]=0;
}
j++;
}
j=1;
while (j<=d && i+j<n && arr[i+j]<arr[i])
{
if (!f[i+j])
{
sum=1;
f[i+j]=1;
sum+=search(i+j,d,arr);
if(sum>ans) ans=sum;
f[i+j]=0;
}
j++;
}
return ans;
}
int maxJumps(vector<int>& arr, int d) {
int ans=0;
int n=arr.size();
for (int i=0; i<n; i++)
{
f[i]=1;
int sum=1;
sum += search(i,d,arr);
if (sum>ans)
ans=sum;
f[i]=0;
}
return ans;
}
};
很显然的超出了时间限制。
为了节省时间,如果之前搜索过的点,那么就可以直接存储并且拿过来用。
class Solution {
public:
bool f[1002]={0};
int a[1002]={0};
int search(int i, int d,vector<int>& arr)
{
if (a[i]) return a[i]-1;
int j=1;
int n=arr.size();
int sum=0;
int ans=0;
while (j<=d && i-j>-1 && arr[i-j]<arr[i])
{
if (!f[i-j])
{
sum=1;
f[i-j]=1;
sum+=search(i-j,d,arr);
if(sum>ans) ans=sum;
f[i-j]=0;
}
j++;
}
j=1;
while (j<=d && i+j<n && arr[i+j]<arr[i])
{
if (!f[i+j])
{
sum=1;
f[i+j]=1;
sum+=search(i+j,d,arr);
if(sum>ans) ans=sum;
f[i+j]=0;
}
j++;
}
return ans;
}
int maxJumps(vector<int>& arr, int d) {
int ans=0;
int n=arr.size();
for (int i=0; i<n; i++)
{
f[i]=1;
int sum=1;
sum += search(i,d,arr);
if (sum>ans)
ans=sum;
a[i]=sum;
f[i]=0;
}
return ans;
}
};
记忆化搜索提高了10个点的通过率,但是依旧失败了。个人感到有一点问题:因为不能保证剔除重复搜索的点。不存在的,因为条件的问题,不会出现环,还是DP做的
class Solution {
public:
int dp[1002]={0};
void search(int i, int d,vector<int>& arr)
{
int n=arr.size();
int j=1;
while (j<=d && i-j>-1 && arr[i]>arr[i-j])
{
if (!dp[i-j]) search(i-j,d,arr);
dp[i]=max(1+dp[i-j],dp[i]);
j++;
}
j=1;
while (j<=d && i+j<n && arr[i]>arr[i+j])
{
if (!dp[i+j]) search(i+j,d,arr);
dp[i]=max(1+dp[i+j],dp[i]);
j++;
}
return;
}
int maxJumps(vector<int>& arr, int d) {
int n=arr.size();
int ans=0;
for (int i=0; i<n; i++)
{
if (!dp[i])
{
int j=1;
while (j<=d && i-j>-1 && arr[i]>arr[i-j])
{
if (!dp[i-j]) search(i-j,d,arr);
dp[i]=max(1+dp[i-j],dp[i]);
j++;
}
j=1;
while (j<=d && i+j<n && arr[i]>arr[i+j])
{
if (!dp[i+j]) search(i+j,d,arr);
dp[i]=max(1+dp[i+j],dp[i]);
j++;
}
}
if (dp[i]>ans) ans=dp[i];
}
return ans+1;
}
};