Easy
题目描述
给你一个下标从 0 开始的整数数组 nums,其中 nums.length == n,找出 nums[i] 和 nums[j] 之间的 最大差值,其中 0 <= i < j < n 且 nums[i] < nums[j]。
返回 最大差值。如果不存在满足要求的 i 和 j,返回 -1。
示例 1:
输入:nums = [7,1,5,4]
输出:4
解释:
最大差值出现在 i = 1 且 j = 2 时,nums[j] - nums[i] = 5 - 1 = 4 。
注意,尽管 i = 1 且 j = 0 时,nums[j] - nums[i] = 7 - 1 = 6 > 4 ,但 i > j ,所以不满足题面要求。
示例 2:
输入:nums = [9,4,3,2]
输出:-1
解释:
不存在同时满足 i < j 和 nums[i] < nums[j] 的 i, j 组合。
示例 3:
输入:nums = [1,5,2,10]
输出:9
解释:
最大差值出现在 i = 0 且 j = 3 时,nums[j] - nums[i] = 10 - 1 = 9 。
提示:
n == nums.length2 <= n <= 10001 <= nums[i] <= 10^9
解题思路
解题思路
这道题要求找到满足 i < j 且 nums[i] < nums[j] 条件下的最大差值 nums[j] - nums[i]。
方法一:暴力枚举(O(n²)) 直接双重循环枚举所有可能的 i 和 j 组合,检查是否满足条件并更新最大差值。
方法二:一次遍历优化(推荐)
关键观察:要使差值 nums[j] - nums[i] 最大,我们需要:
nums[i]尽可能小nums[j]尽可能大(且位置在nums[i]之后)
算法思路:
- 从左到右遍历数组,维护到目前为止遇到的最小值
- 对于每个位置 j,计算
nums[j] - min_val的差值 - 只有当
nums[j] > min_val时,这个差值才是有效的 - 不断更新最大差值
这样只需要一次遍历就能找到答案,时间复杂度降到 O(n)。
特殊情况处理:如果整个数组是严格递减的,那么不存在满足条件的 i 和 j,返回 -1。
代码实现
class Solution {
public:
int maximumDifference(vector<int>& nums) {
int maxDiff = -1;
int minVal = nums[0];
for (int j = 1; j < nums.size(); j++) {
if (nums[j] > minVal) {
maxDiff = max(maxDiff, nums[j] - minVal);
}
minVal = min(minVal, nums[j]);
}
return maxDiff;
}
};
class Solution:
def maximumDifference(self, nums: List[int]) -> int:
max_diff = -1
min_val = nums[0]
for j in range(1, len(nums)):
if nums[j] > min_val:
max_diff = max(max_diff, nums[j] - min_val)
min_val = min(min_val, nums[j])
return max_diff
public class Solution {
public int MaximumDifference(int[] nums) {
int maxDiff = -1;
int minVal = nums[0];
for (int j = 1; j < nums.Length; j++) {
if (nums[j] > minVal) {
maxDiff = Math.Max(maxDiff, nums[j] - minVal);
}
minVal = Math.Min(minVal, nums[j]);
}
return maxDiff;
}
}
var maximumDifference = function(nums) {
let maxDiff = -1;
let minVal = nums[0];
for (let j = 1; j < nums.length; j++) {
if (nums[j] > minVal) {
maxDiff = Math.max(maxDiff, nums[j] - minVal);
}
minVal = Math.min(minVal, nums[j]);
}
return maxDiff;
};
复杂度分析
| 解法 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 一次遍历 | O(n) | O(1) |
| 暴力枚举 | O(n²) | O(1) |
推荐解法:一次遍历
- 时间复杂度:O(n),只需要遍历数组一次
- 空间复杂度:O(1),只使用了常数级别的额外空间