1、前言
本篇继续整理Hot150。
1、H指数
1.1.描述
给定一个数组,里面每个元素表示作者论文的引用数量。H指数:表示发表了H篇论文,且有H篇论文被引用了H次。返回H中最大的那个值。
1.2.思路
题目描述比较混乱,直接说思路,由大到小排序,然后遍历每个元素,当元素值>i时,则累加H指数。
class Solution:
def hIndex(self, citations: List[int]) -> int:
citations.sort(reverse=True)
h = 0
for i in range(len(citations)):
if citations[i] > i : # 这里到底是 > 还是 >= 可能拿捏不准,记住[0]这个例子,h=0;
h += 1
else:
break
return h
2、除自身以外数组的乘积
2.1.描述
给你一个数组Nums,返回一个ans数组,里面每个元素表示nums数组中除了自身以外,其余元素的乘积:举个例子:
nums=[1,2,3],返回ans=[6,3,2]
2.2.思路
首先存储下来当前元素,所有左边元素的乘积和右边元素的乘积。然后分别从左右两边取元素便能得到ans的乘积。
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
# 左边元素所有乘积
left = []
for i in range(len(nums)):
if i == 0:
left.append(1)
else:
ele = nums[i-1] * left[i-1]
left.append(ele)
# 右边元素所有乘积
right = []
for i in range(len(nums)-1, -1, -1):
if i == len(nums) - 1:
right.append(1)
else:
# i的后一个坐标
ele = nums[i+1] * right[len(nums)-2-i]
right.append(ele)
# 遍历每个元素
ans = []
for l, r in zip(left, right[::-1]):
ans.append(l*r)
return ans
3、加油站
3.1.描述
给定一个加油的数组 和 去下个加油站的耗油数组,问从哪个加油站出发,能够完整的循环一圈?
3.2.思路
上来先判断,若总的加油数组和比总的耗油数组和小,则一定不够行驶一圈,直接返回-1;假设从i站出发,能行驶到j站,但是行驶不到j+1站;则将起始位置调整为j+1站,继续循环。
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
if sum(gas) < sum(cost) : return -1
start_idx = 0 # 起始位置
curSum = 0 # 从i到j的累加加油和
for i in range(0, len(gas)):
if curSum < 0:
curSum = 0
start_idx = (i) % len(gas) # 若不满足,则将起始位置调整为下一站;
curSum += (gas[i] - cost[i] ) # 累加
return start_idx
4、分发糖果
4.1.描述
N个孩子站成一排,有个分数数组,现在要求给每个孩子按照分数分发糖果,要求:每个孩子至少有一个糖果;得分高的孩子需要比得分低的孩子糖果多。返回至少得发多少个糖果?
输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。
4.2.思路
将问题拆分成两个问题:先遍历满足左规则:即若右边孩子比左边孩子得分高,就比左边孩子多一个糖果;否则仅给一个。然后在相反遍历右规则,最后同时遍历左右规则,取最大的糖果数目累加即可。
class Solution:
def candy(self, ratings: List[int]) -> int:
# 左遍历:若右边孩子比左边孩子分数高,则多发一个糖果
left = []
for i in range(len(ratings)):
if i == 0:
left.append(1) # 初始孩子手里有一个糖果
else:
if ratings[i] > ratings[i-1]:
left.append(left[i-1]+1)
else:
left.append(1)
right = []
for i in range(len(ratings)-1, -1, -1):
if i == len(ratings) - 1:
right.append(1)
else:
if ratings[i] > ratings[i+1]:
right.append(right[len(ratings)-1-1-i]+1)
else:
right.append(1)
# 当前这个孩子需要同时满足左右两边规则
ans = 0
for l,r in zip(left, right[::-1]):
ans += (max(l, r))
return ans
5、接雨水
5.1.描述
给定一个高度数组,问由这些高度导致的低洼能接多少单位雨水?宽度为1。
5.2.思路
从左遍历记录最高高度,从右遍历记录最高高度。然后二者取最小值减去当前高度即是接雨水的高度。示例图可参考官方题解。
class Solution:
def trap(self, height: List[int]) -> int:
# 记录从左到右的最大高度
leftmax = []
for i in range(len(height)):
if i == 0:
leftmax.append(height[0])
else:
leftmax.append(max(height[i], leftmax[i-1]))
# 记录从右到左的最大高度
rightmax = []
for i in range(len(height)-1, -1, -1):
if i == len(height) -1 :
rightmax.append(height[-1])
else:
rightmax.append(max(rightmax[len(height)-1-1-i], height[i]))
# 遍历,取二者最小值
ans = 0
for i in range(len(height)):
max_l = leftmax[i]
max_r = rightmax[len(height)-1-i]
ans += (min(max_l, max_r) - height[i]) # 取出二者最小值,减去当前高度
return ans
总结
15道了…