每日一题 - 中等 - 长度为 K 子数组中的最大和(2461)

107 阅读2分钟

题目:

给你一个整数数组 nums 和一个整数 k 。请你从 nums 中满足下述条件的全部子数组中找出最大子数组和:

  • 子数组的长度是 k,且
  • 子数组中的所有元素 各不相同 。

返回满足题面要求的最大子数组和。如果不存在子数组满足这些条件,返回 0 。

子数组 是数组中一段连续非空的元素序列。

示例 :

输入:nums = [1,5,4,2,9,9,9], k = 3
输出:15
解释:nums 中长度为 3 的子数组是:
- [1,5,4] 满足全部条件,和为 10 。
- [5,4,2] 满足全部条件,和为 11 。
- [4,2,9] 满足全部条件,和为 15 。
- [2,9,9] 不满足全部条件,因为元素 9 出现重复。
- [9,9,9] 不满足全部条件,因为元素 9 出现重复。
因为 15 是满足全部条件的所有子数组中的最大子数组和,所以返回 15 。

思路 数组中连续子串的最大最小值之类的题目,基本是使用滑动窗口的形式

解题方法

1.定义的变量有:左右指针,最大值,当前窗口的和,当前窗口map

  1. 左右指针都从0开始,每次移动一步右指针,并将值加入到当前窗口的和(+)

  2. 判断当前map中是否存在重复的元素,如果重复 则将左指针指向到右指针,右指针继续向前移动(本题真是可行的), 否则判断当前窗口的数量是否等于k, 如果等于k则将当前窗口的和与结果返回值比较,去两者中更大的作为返回值,同时也将窗口左边向前移动一位

function maximumSubarraySum(nums, k) {
	if ([...new Set(nums)].length < k) return 0
  let result = 0
  let tempResult = 0
  let l = 0,
    r = 0,
    length = nums.length
  let map = new Map()
  while (r < length) {
    map.set(nums[r], map.get(nums[r]) + 1 || 1)
    tempResult += nums[r]
    if (map.get(nums[r]) > 1) {
      map.clear()
      l = r
      tempResult = nums[l]
      map.set(nums[l], 1)
    } else if (map.size >= k) {
      map.delete(nums[l])
      result = Math.max(result, tempResult)
      tempResult -= nums[l]
      l++
    }
    r++
  }
  return result
}

ps: 本题是本周的周赛题,没写出来,超时了,所以来总结一下,如果是按照我的计划是现在不考虑中等题的