2021-04-10 19:50:25
跳跃游戏II
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
假设现在在位置 k k k,那么能跳的步数 s t e p ≤ n u m s [ k ] step \leq nums[k] step≤nums[k],问你从起点跳到终点最少需要多少步。
设 a [ i ] a[i] a[i]为跳到第 i i i位所需要的最少步数,那么 a [ i ] = m i n ( a [ i ] , a [ i − k ] + 1 ) a[i] = min(a[i], a[i-k]+1) a[i]=min(a[i],a[i−k]+1), k k k为某一位跳 k k k步到 i i i。
class Solution {
public:
int jump(vector<int>& nums) {
int n = nums.size();
vector<int>a(n,0x3f3f3f3f);
a[0] = 0;
for(int i=0;i<n;++i) {
for(int j=1;j<=nums[i];++j) {
if(i+j <=n-1)
a[i+j] = min(a[i] + 1,a[i+j]);
}
}
return a[n-1];
}
};
这样写其实没有什么贪心的思想。。
如果用贪心来考虑呢?从起点开始,那就要跳到尽可能跳的远的点,比如例子
[
2
,
3
,
1
,
1
,
4
]
[2,3,1,1,4]
[2,3,1,1,4],第一个点可以跳到下标为
1
,
2
1,2
1,2的点,下标为1的最远可以跳到
4
4
4,下标为2的最远可以跳到3,所以选择跳到下标为1的。
int n = nums.size();
int maxPos = 0, ans = 0, e = 0;
for(int i=0; i<n-1; ++i) {
if(maxPos >= i) {
maxPos = max(maxPos, i + nums[i]);
if( i == e) {
e = maxPos;
ans ++;
}
}
}
return ans;
跳跃游戏
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
这题和上题很像,不过是判断能不能到达最后一个点。
这次不需要求最小步数,所以可以维护每个点所能到达的最远点,然后判断大不大于
n
−
1
n-1
n−1。
int w = 0;
for(int i=0;i<n;++i) {
if(i > w) return false;
w = max(w, i + nums[i]);
}
return true;
买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
可以多次购买售出股票。
如果用dp来做,设
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0]表示第
i
i
i时刻并且手上没有股票的最大利润,
d
p
[
i
]
[
1
]
dp[i][1]
dp[i][1]表示第
i
i
i时刻并且手上有一只股票的最大利润。
可以写出状态转移方程,
d
p
[
i
]
[
0
]
=
m
a
x
(
d
p
[
i
−
1
]
[
0
]
,
d
p
[
i
−
1
]
[
1
]
+
p
r
i
c
e
s
[
i
]
)
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][0]=max(dp[i−1][0],dp[i−1][1]+prices[i])
可以不买,或者在第i时刻卖了
d
p
[
i
]
[
1
]
=
m
a
x
(
d
p
[
i
−
1
]
[
1
]
,
d
p
[
i
−
1
]
[
0
]
−
p
r
i
c
e
s
[
i
]
)
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
dp[i][1]=max(dp[i−1][1],dp[i−1][0]−prices[i])
可以在第i时刻不卖,或者在第i时刻买了
d p [ 0 ] [ 0 ] = 0 , d p [ 0 ] [ 1 ] = − p r i c e s [ 0 ] dp[0][0] = 0,dp[0][1] = -prices[0] dp[0][0]=0,dp[0][1]=−prices[0]
考虑贪心,只要第 i i i时刻的股票价格比第 i − 1 i-1 i−1时刻高,就卖了。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int ans = 0;
for(int i=1;i<prices.size();++i) {
if(prices[i] > prices[i-1]) ans+=prices[i]-prices[i-1];
}
return ans;
}
};
加油站
在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。
你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。
如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。
说明:
如果题目有解,该答案即为唯一答案。
输入数组均为非空数组,且长度相同。
输入数组中的元素均为非负数。
这题数据范围应该不大,暴力就能过。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int n = gas.size();
vector<int>a(n,0);
for(int i=0;i<n;++i) a[i] = gas[i] - cost[i];
for(int i=0;i<n;++i) {
if(a[i] >= 0) {
int j=(i+1)%n,g=a[i];
bool ok = true;
while(j!=i) {
g += a[j];
j = (j+1)%n;
if(g<0) {
ok = false;
break;
}
}
if(ok) return i;
}
}
return -1;
}
};