Medium
题目描述
给你一个长度为 n 的整数数组 nums 和一个正整数 k。
数组的能量值定义为:
- 如果数组中的所有元素都是连续且按升序排列的,则能量值为数组的最大元素
- 否则为 -1
你需要找到 nums 中所有长度为 k 的子数组的能量值。
返回一个长度为 n - k + 1 的整数数组 results,其中 results[i] 是 nums[i..(i + k - 1)] 的能量值。
示例 1:
输入:nums = [1,2,3,4,3,2,5], k = 3
输出:[3,4,-1,-1,-1]
解释:
nums 中有 5 个长度为 3 的子数组:
- [1, 2, 3],最大元素为 3
- [2, 3, 4],最大元素为 4
- [3, 4, 3],元素不连续
- [4, 3, 2],元素不是升序
- [3, 2, 5],元素不连续
示例 2:
输入:nums = [2,2,2,2,2], k = 4
输出:[-1,-1]
示例 3:
输入:nums = [3,2,3,2,3,2], k = 2
输出:[-1,3,-1,3,-1]
提示:
- 1 <= n == nums.length <= 500
- 1 <= nums[i] <= 10^5
- 1 <= k <= n
解题思路
这道题需要判断每个长度为 k 的子数组是否满足"连续且升序"的条件。
解题思路
方法一:暴力解法
- 对于每个起始位置 i,检查子数组 nums[i..i+k-1]
- 验证相邻元素是否连续(差值为1)且升序
- 如果满足条件,返回最大值(即最后一个元素);否则返回 -1
- 时间复杂度 O(n*k),适合题目约束条件
方法二:滑动窗口优化
- 预处理:计算每个位置开始的连续递增序列长度
- 使用滑动窗口,如果当前窗口的连续长度 >= k,则满足条件
- 时间复杂度 O(n),空间复杂度 O(n)
由于题目约束 n ≤ 500,两种方法都可行。这里推荐方法一,代码简洁易懂。
核心逻辑:
- 遍历所有可能的起始位置
- 对每个子数组,检查是否严格递增且连续
- 连续意味着 nums[j] = nums[j-1] + 1
- 如果整个子数组满足条件,最大值就是最后一个元素
代码实现
class Solution {
public:
vector<int> resultsArray(vector<int>& nums, int k) {
int n = nums.size();
vector<int> results(n - k + 1);
for (int i = 0; i <= n - k; i++) {
bool isValid = true;
for (int j = i + 1; j < i + k; j++) {
if (nums[j] != nums[j - 1] + 1) {
isValid = false;
break;
}
}
results[i] = isValid ? nums[i + k - 1] : -1;
}
return results;
}
};
class Solution:
def resultsArray(self, nums: List[int], k: int) -> List[int]:
n = len(nums)
results = []
for i in range(n - k + 1):
is_valid = True
for j in range(i + 1, i + k):
if nums[j] != nums[j - 1] + 1:
is_valid = False
break
if is_valid:
results.append(nums[i + k - 1])
else:
results.append(-1)
return results
public class Solution {
public int[] ResultsArray(int[] nums, int k) {
int n = nums.Length;
int[] results = new int[n - k + 1];
for (int i = 0; i <= n - k; i++) {
bool isValid = true;
for (int j = i + 1; j < i + k; j++) {
if (nums[j] != nums[j - 1] + 1) {
isValid = false;
break;
}
}
results[i] = isValid ? nums[i + k - 1] : -1;
}
return results;
}
}
var resultsArray = function(nums, k) {
const n = nums.length;
const results = [];
for (let i = 0; i <= n - k; i++) {
let isValid = true;
for (let j = i + 1; j < i + k; j++) {
if (nums[j] !== nums[j - 1] + 1) {
isValid = false;
break;
}
}
results.push(isValid ? nums[i + k - 1] : -1);
}
return results;
};
复杂度分析
| 复杂度 | 暴力解法 | 滑动窗口优化 |
|---|---|---|
| 时间复杂度 | O(n × k) | O(n) |
| 空间复杂度 | O(1) | O(n) |
说明:
- n 为数组长度
- 暴力解法:对每个子数组都需要 O(k) 时间验证,共有 O(n) 个子数组
- 滑动窗口:预处理 O(n),查询 O(1)
- 由于题目约束 n ≤ 500,暴力解法完全够用且代码更简洁