这是我参与11月更文挑战的第14天,活动详情查看2021最后一次更文挑战
链接
题目
2089. 找出数组排序后的目标下标
统计
解析
由于最后要求的是排序之后target元素起始与末尾的序号,只需一遍统计数组中比target元素小的个数和target元素的个数即可。
代码
class Solution:
def targetIndices(self, nums: List[int], target: int) -> List[int]:
smallCount, targetCount = 0, 0
for num in nums:
if num < target:
smallCount += 1
elif num == target:
targetCount += 1
return [i for i in range(smallCount, smallCount + targetCount)]
排序后查找
解析
首先对数组进行升序排序,然后用直接遍历或二分查找的方式找出target元素的起止位置。
虽然数据规模n<=100不会对时间复杂度(O(nlogn)比O(n))造成特别大的影响,但是这种方式还是不如直接统计的方法方便简洁。
代码
class Solution:
def targetIndices(self, nums: List[int], target: int) -> List[int]:
nums.sort()
if nums[0] > target or nums[-1] < target:
return []
else:
left = 0
n = len(nums)
while left < n and nums[left] < target:
left += 1
right = left
while right < n and nums[right] == target:
right += 1
return [ind for ind in range(left, right)]
2090. 半径为 k 的子数组平均值
滑动窗口
解析
这道题是一道较简单的滑动窗口题目,除去需要判断哪些位置取-1的情况外,基本上就是求对应位置左右范围内滑动窗口的元素和,每移动一次时窗口左右指针都移动一次即可。
代码
这份代码没有明显记录左右指针,因为左右指针所处的位置可以直接通过i和k计算出来
class Solution:
def getAverages(self, nums: List[int], k: int) -> List[int]:
n = len(nums)
ans = []
currSum = sum(nums[0 : (2*k + 1)])
for i, num in enumerate(nums):
if i - k < 0 or i + k >= n:
ans.append(-1)
else:
ans.append(currSum // (2*k + 1))
if i+k+1 < n:
currSum += nums[i+k+1] - nums[i-k]
return ans
前缀和
解析
判断-1的情况和滑动窗口的思路类似,区别在于前缀和提前求和、后续能在O(1)时间将范围和求出
代码
class Solution:
def getAverages(self, nums: List[int], k: int) -> List[int]:
n = len(nums)
prevSum = [0] * (n+1)
for i in range(n):
prevSum[i+1] = nums[i] + prevSum[i]
ans = []
for i in range(n):
if i - k < 0 or i + k >= n:
ans.append(-1)
else:
ans.append((prevSum[i + k + 1] - prevSum[i - k]) // (2*k + 1))
return ans