• 1330. Reverse Subarray To Maximize Array Value


    问题:

    给定数组,假定value=数组相邻元素两两之差(绝对值)的总和。

    允许对数组内某一个连续子数组进行整体反转,使得value能取得最大。求这样的value。

    Example 1:
    Input: nums = [2,3,1,5,4]
    Output: 10
    Explanation: By reversing the subarray [3,1,5] the array becomes [2,5,1,3,4] whose value is 10.
    
    Example 2:
    Input: nums = [2,4,9,24,2,1,10]
    Output: 68
    Explanation: By reversing the subarray [24,2] the array becomes [2,4,9,2,24,1,10] 
    whose value is 68.
     
    Constraints:
    1 <= nums.length <= 3*10^4
    -10^5 <= nums[i] <= 10^5
    

      

    解法:

    对于数组:A[0]..., a, [b, ..., c], d, ...A[size-1]

    子数组[b, ..., c]反转,对于原数组得到的value的差值为:

    原先的两头元素差值,被新的两头元素差值替换

    要求的

    value = 原先的所有相邻元素差值orig_res + 反转前后的差值reversediff

    即可。

    接下来,我们讨论,反转前后的差值reversediff的求解:

    反转的方式有三种情况:(我们只需在各种情况中取最大的结果即可)

    从头开始的左数组:         A[0]~a,b...        ->   a~A[0],b...       :leftbounddiff 反转前后的差值为:-abs(a-b) + abs(A[0]-b)
    以最后元素结束的右数组:...a,b~A[size-1] -> ...a,A[size-1]~b   :rightbounddiff 反转前后的差值为:-abs(a-b) + abs(a-A[size-1])
    中间数组:                     ..., a, b, ..., c , d, ... -> ..., a, c, ..., b , d, ...   :反转前后的差值为:-(abs(a-b)+abs(c-d)) + (abs(a-c)+abs(b-d))

    对于中间数组,我们分以下三种情况,进行讨论:(经过下面的分析,我们最终只选择第3种情况。)

    1. [a,b] 和 [c,d] 有相交:

    则其reverse前的两头元素差值:如下图红线的和:

    reverse后,有两种情况:分别为蓝线绿线的和,

    如下图可知,进行reverse后,红线之和>=蓝线or绿线之和。因此反转并没有使得差值变大。

    因此我们不选择将这段[b~c]进行反转。


    2. [a,b] 和 [c,d] 有互相包含的关系:

    如下图可知,进行reverse后,同样的,红线之和>=蓝线or绿线之和。因此反转并没有使得差值变大。

    因此我们不选择将这段[b~c]进行反转。

     

    3. [a,b] 和 [c,d] 无相交:

    如下图可知,进行reverse后,红线之和<蓝线==绿线之和。

    反转,使得差值变大,这正是我们会选择反转的备选之一。

    这时,反转前后的差值 = 2 * 黄线

    黄线=min(c,d)-max(a,b) = cdlow-abhigh,其中 a和b < c和d

    我们要使得反转后的value能取得最大,也就是使得黄线越大。

    我们只需要取得a和b最小minabhighc和d最大maxcdlow,那么其差值即越大。

     

    代码参考:

     1 class Solution {
     2 public:
     3     int maxValueAfterReverse(vector<int>& nums) {
     4         int orig_res=0;
     5         int reversediff=0;
     6         int maxcdlow=INT_MIN, minabhigh=INT_MAX;
     7         int leftbounddiff=0, rightbounddiff=0;
     8         for(int i=0; i<nums.size()-1; i++){
     9             orig_res+=abs(nums[i]-nums[i+1]);
    10             
    11             //为了求最后,中间数组reverse的结果=2*(maxcdlow-minabhigh)
    12             minabhigh=min(minabhigh, max(nums[i], nums[i+1]));
    13             maxcdlow=max(maxcdlow, min(nums[i], nums[i+1]));
    14             
    15             //左右两边数组reverse的情况:
    16             leftbounddiff=-abs(nums[i]-nums[i+1])+abs(nums[0]-nums[i+1]);
    17             rightbounddiff=-abs(nums[i]-nums[i+1])+abs(nums[nums.size()-1]-nums[i]);
    18             //-(原来的ab之差)+(新的ab之差)
    19             reversediff=max(reversediff, max(leftbounddiff, rightbounddiff));
    20             //求reverse改变差值最大的,作为新的reversediff
    21         }
    22         reversediff=max(reversediff, 2*(maxcdlow-minabhigh));
    23         return orig_res+reversediff;
    24     }
    25 };
  • 相关阅读:
    排序_简单选择排序
    排序_冒泡排序
    笔试_阿里_逆波兰表达式
    刷题_牛客_大整数排序
    刷题_牛客_字符串编码
    刷题_thinkinginjava_吸血鬼数字
    刷题_牛客_超级素数幂
    刷题_LeetCode_Two Sum
    刷题_LeetCode_Reverse Integer
    854. Floyd求最短路(模板)
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/12992939.html
Copyright © 2020-2023  润新知