借助一个额外数据将各个元素放到新位置。注意到从整体上看,输出数组可以看作是在 k % len(nums) 位置截断然后重新组合,可以用 python 的列表操作简单地如下实现
classSolution:defrotate(self, nums: List[int], k:int)->None:
k = k %len(nums)
res = nums[-k:]+ nums[:-k]
nums[:]= res
这其实等价于用两个指针分别遍历截断的两部分,并将元素依次复制到辅助数组
时间复杂度
O
(
n
)
O(n)
O(n),空间复杂度
O
(
n
)
O(n)
O(n)
6.2 解法2:数组翻转
和方法一一样,注意到输出数组可以看作是在 k % len(nums) 位置截断然后重新组合,这可以通过三次列表翻转实现,示意如下
nums = "----->-->"; k =3
result = "-->----->";
reverse "----->-->" we can get "<--<-----"
reverse "<--" we can get "--><-----"
reverse "<-----" we can get "-->----->"
下面给出代码,使用双指针进行翻转操作
classSolution:defrotate(self, nums: List[int], k:int)->None:def_reverse(start, end):while start < end:
t = nums[start]
nums[start]= nums[end]
nums[end]= t
start +=1
end -=1
k = k %len(nums)
_reverse(0,len(nums)-1)
_reverse(0, k-1)
_reverse(k,len(nums)-1)
我们使用自底向上的动态规划形式,这时需要构造递推公式(动态规划中称 “状态转移方程”)。定义状态 dp[i][0] 和 dp[i][1] 分别表示第
i
i
i 天交易完后手里没有和持有股票的最大利润。
对于 dp[i][0] 来说,第
i
i
i 天交易完后手里没有股票,意味着要么前一天就没有,要么今天卖了,递推式为
d
p
[
i
]
[
0
]
=
max
{
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]}
对于 dp[i][1] 来说,第
i
i
i 天交易完后手里有股票,意味着要么前一天有,要么今天刚买,递推式为
d
p
[
i
]
[
1
]
=
max
{
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]}
根据问题定义,第0天交易时有
d
p
[
0
]
[
0
]
=
0
,
d
p
[
0
]
[
1
]
=
−
p
r
i
c
e
s
[
0
]
dp[0][0]=0,\quad dp[0][1]=−prices[0]
dp[0][0]=0,dp[0][1]=−prices[0]
由于全部交易结束后,持有股票的收益一定低于不持有股票的收益,最后返回
d
p
[
n
−
1
]
[
0
]
dp[n−1][0]
dp[n−1][0] 即可
对于每一个可达位置
x
x
x,它使得
x
+
1
,
x
+
2
,
⋯
,
x
+
nums
[
x
]
x+1,x+2,⋯ ,x+\text{nums}[x]
x+1,x+2,⋯,x+nums[x] 这些连续的位置都可以到达。利用贪心的思想,我们遍历数组,并在每一步维护当前可达的最大状态,如果发现最后的位置可达则返回 true,反之若遍历结束后最后位置仍不可达则返回 false
classSolution:defcanJump(self, nums: List[int])->bool:
max_range =0for i, step inenumerate(nums):if i <= max_range:if i + step > max_range:
max_range = i + step
if max_range >=len(nums)-1:returnTruereturnFalse