【1330. 翻转子数组得到最大的数组值】

来源:力扣(LeetCode)

描述:

给你一个整数数组 nums 。「数组值」定义为所有满足 0 <= i < nums.length-1|nums[i]-nums[i+1]| 的和。

你可以选择给定数组的任意子数组,并将该子数组翻转。但你只能执行这个操作 一次

请你找到可行的最大 数组值

示例 1:

输入:nums = [2,3,1,5,4]
输出:10
解释:通过翻转子数组 [3,1,5] ,数组变成 [2,5,1,3,4] ,数组值为 10

示例 2:

输入:nums = [2,4,9,24,2,1,10]
输出:68

提示:

  • 1 <= nums.length <= 3*104
  • -105 <= nums[i] <= 105

方法:枚举所有可能性

思路

设数组 nums 的长度为 n。原数组的数组值的表达式为 value1 = ∑ i = 0 n − 2 \sum_{i=0}^{n−2} i=0n2∣nums[i + 1] − nums[i]∣。假设我们选择起点下标为 j,终点下标为 k (j ≤ k) 的子数组进行翻转,下面进行讨论:

  1. j = k,此时不难发现执行翻转操作后的数组的数组值 value2 = value1
  2. j = 0 且 k = n − 1,此时 value2 = value1
  3. j = 0 且 k < n − 1,此时 value2 = ∑ i = 0 k − 1 \sum_{i=0}^{k−1} i=0k1 ∣nums[i + 1] − nums[i]∣ + ∣nums[k + 1] − nums[0]∣ + ∑ i = k + 1 n − 1 \sum_{i=k+1}^{n−1} i=k+1n1 ∣nums[i + 1] − nums[i]∣。可以得到 value2 = value1 − ∣nums[k + 1] − nums[k]∣ + ∣nums[k + 1] − nums[0]∣。这种情况下 value2 的最大值可以通过遍历 k 获得。
  4. j > 0 且 k = n − 1。此时 value2 = value1 − ∣nums[j] − nums[j − 1]∣ + ∣nums[n − 1] − nums[j − 1]∣。这种情况下 value2 的最大值可以通过遍历 j 获得。
  5. j > 0 且 k < n − 1。此时 value2 = value1 − ∣nums[j] − nums[j − 1]∣ − ∣nums[k + 1] − nums[k]∣ + ∣nums[k] − nums[j − 1]∣ + ∣nums[k + 1] − nums[j]∣。令 δ = −∣nums[j] − nums[j − 1]∣ − ∣nums[k + 1] − nums[k]∣ + ∣nums[k] − nums[j − 1]∣ + ∣nums[k + 1] − nums[j]∣,则 value2 = value1 + δ。因为 value1 为定值,为了使 value2 取得最大值,需要求出 δ 的最大值。这种情况下 δ 的最大值可以通过双重遍历 j 和 k 获得,但会带入较大的时间复杂度。为了降低时间复杂度,仍要进行讨论。假设 nums[j − 1], nums[j], nums[k], nums[k + 1] 四个数由小到大排列的值分别为 a, b, c, d,下面进行讨论:
  • ∣nums[j] − nums[j − 1]∣ = b − a,∣nums[k + 1] − nums[k]∣ = d − c,则 δ = −(b − a) − (d − c) + nums[k − nums[j − 1] + nums[k + 1] − nums[j] = 2 × (c − b)。
  • ∣nums[j] − nums[j − 1]∣ = d − c,∣nums[k + 1] − nums[k]∣= b − a,则 δ = −(d − c) − (b − a − nums[k] + nums[j − 1] − nums[k + 1] + nums[j] = 2 × (c − b)。即同上。
  • ∣nums[j] − nums[j − 1]∣ = c − a,∣nums[k + 1] − nums[k]∣= d − b。此时 δ = a + b − c − d + ∣nums[k] − nums[j − 1]∣ + ∣nums[k + 1] − nums[j]∣。可以发现这时 δ 不可能为正数,因为最大的两项已经为负数,后四项为两正两负,无法使 δ 为正数。
  • ∣nums[j] − nums[j − 1]∣ = d − a,∣nums[k + 1] − nums[k]∣ = c − b。此时 δ = a + b − c − d + ∣nums[k]− nums[j − 1]∣ + ∣nums[k + 1] − nums[j]∣。同上。
  • ∣nums[j] − nums[j − 1]∣ = c − b,∣nums[k + 1] − nums[k]∣ = d − a。同上。
  • ∣nums[j] − nums[j − 1]∣ = d − b,∣nums[k + 1] − nums[k]∣ = c − a。同上。

讨论完六种情况后发现只有两种情况下 δ 可能为正。这两种情况下,均是求 2 × (c − b)。即两个相邻数对,当一个数对的较大值小于另一个数对的较小值时,求差值的两倍。我们需要求出这个差值的两倍的最大值。求出 δ 的最大值后,加上 value1 ,即为 value2 的最大值。

最后再求出这五种情况下的最大值即可返回结果。

代码:

class Solution {
public:
    int maxValueAfterReverse(vector<int>& nums) {
        int value = 0, n = nums.size();
        for (int i = 0; i < n - 1; i++) {
            value += abs(nums[i] - nums[i + 1]);
        }
        int mx1 = 0;
        for (int i = 1; i < n - 1; i++) {
            mx1 = max(mx1, abs(nums[0] - nums[i + 1]) - abs(nums[i] - nums[i + 1]));
            mx1 = max(mx1, abs(nums[n - 1] - nums[i - 1]) - abs(nums[i] - nums[i - 1]));
        }
        int mx2 = INT_MIN, mn2 = INT_MAX;
        for (int i = 0; i < n - 1; i++) {
            int x = nums[i], y = nums[i + 1];
            mx2 = max(mx2, min(x, y));
            mn2 = min(mn2, max(x, y));
        }
        return value + max(mx1, 2 * (mx2 - mn2));
    }
};

执行用时:48 ms, 在所有 C++ 提交中击败了96.97%的用户
内存消耗:39.2 MB, 在所有 C++ 提交中击败了89.39%的用户
复杂度分析
时间复杂度:O(n),其中 n 是输入数组 nums 的长度。
空间复杂度:O(1)。仅使用常数空间。
author:LeetCode-Solution

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千北@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值