Python蓝桥杯训练:数组和字符串 Ⅴ
文章目录
- Python蓝桥杯训练:数组和字符串 Ⅴ
- 一、找到数组的中间位置
- 二、使用最小花费爬楼梯
一、找到数组的中间位置
给你一个下标从 0 开始的整数数组 nums ,请你找到 最左边 的中间位置 middleIndex (也就是所有可能中间位置下标最小的一个)。
中间位置 middleIndex 是满足 nums[0] + nums[1] + … + nums[middleIndex-1] == nums[middleIndex+1] + nums[middleIndex+2] + … + nums[nums.length-1] 的数组下标。
如果 middleIndex == 0 ,左边部分的和定义为 0 。类似的,如果 middleIndex == nums.length - 1 ,右边部分的和定义为 0 。
请你返回满足上述条件 最左边 的 middleIndex ,如果不存在这样的中间位置,请你返回 -1 。
示例1:
输入:nums = [2,3,-1,8,4] 输出:3 解释: 下标 3 之前的数字和为:2 + 3 + -1 = 4 下标 3 之后的数字和为:4 = 4
示例2:
输入:nums = [1,-1,4] 输出:2 解释: 下标 2 之前的数字和为:1 + -1 = 0 下标 2 之后的数字和为:0
示例3:
输入:nums = [2,5] 输出:-1 解释: 不存在符合要求的 middleIndex 。
示例4:
输入:nums = [1] 输出:0 解释: 下标 0 之前的数字和为:0 下标 0 之后的数字和为:0
我对这题的解答思路就是首先判断输入的数组长度是否为1,是的话就返回0,然后使用range
遍历,范围为数组本身的长度len(sums)
,然后就是直接判断前i
项的和是否等于后面的和就行。
具体实现代码如下:
class Solution:
def findMiddleIndex(self, nums):
n = len(nums)
if n == 1:
return 0
for i in range(len(nums)):
if sum(nums[:i]) == sum(nums[i + 1:n]):
return i
return -1
这题可以有多种写法,也可以首先计算整个数组的总和,然后再遍历范围为数组本身长度,计算总和,然后将当前索引处的元素从总和中减去,如果当前元素之和等于剩余元素之和,则返回当前索引。如果没有找到,则返回-1。
具体实现代码如下:
class Solution(object):
def findMiddleIndex(self, nums):
total = sum(nums)
x = 0
for i in range(len(nums)):
total -= nums[i]
if x == total:
return i
x += nums[i]
return -1
二、使用最小花费爬楼梯
给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费
示例1:
输入:cost = [10,15,20] 输出:15 解释:你将从下标为 1 的台阶开始。 - 支付 15 ,向上爬两个台阶,到达楼梯顶部。 总花费为 15 。
示例2:
输入:cost = [1,100,1,1,1,100,1,1,100,1] 输出:6 解释:你将从下标为 0 的台阶开始。 - 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。 - 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。 - 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。 - 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。 - 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。 - 支付 1 ,向上爬一个台阶,到达楼梯顶部。 总花费为 6 。
这个题目有点难理解,很容易就想不明白,这个题目有个隐含条件,那就是我们要从地面开始跨台阶,题目给出的数组只是台阶数,我们还需要理解的是还包括地面和楼顶,虽然在现实生活中,到达最顶的台阶就已经是楼顶了,但这个题和现实生活不一样,我也不太明白,看了大佬们的理解才发现的。
题目中你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
含义就是你从地面到第一个台阶和第二个台阶是不花钱的,因此考虑最少花费我们可以不用管第一和第二个台阶,直接从第三个台阶开始,对应下标就是2
,因为我们需要通过判断从当前位置到下一个台阶所需费用和到下一个的下一个台阶所需费用谁便宜来选择跨一步还是跨两步,因此我们可以逆向思维判断下从前一个台阶过来花费少,还是从前一个的前一个过来花费少,一直累加到最后一个台阶完,最小值就是花费最少的。
这个题目考察的也是动态规划,我们需要用到状态转移方程,我们需要首先定义一个n+1
的数组dp
,然后从下标2开始遍历,然后判断两种选择谁花费最少。
具体实现代码如下:
class Solution:
def minCostClimbingStairs(self, cost):
n = len(cost)
dp = [0] * (n + 1)
for i in range(2, n + 1):
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])
return dp[n]
其中dp[i - 1] + cost[i - 1]
表示到达i-1
位置最小费用加上选择从i-1
位置到达楼顶所需费用,后面的dp[i - 2] + cost[i - 2]
也是类似意思。
然后我查看了一下还可以使用滚动数组的思想优化代码:
class Solution:
def minCostClimbingStairs(self, cost):
pre1,pre2 = 0, 0
for i in range(2, len(cost)+1):
pre1,pre2 =pre2, min(pre2 + cost[i-1], pre1 + cost[i-2])
return pre2