翻转子数组得到最大的数组值

数组值定义为所有相邻元素差值的绝对值之和
翻转任意连续的子数组一次,求可行的最大值

1. 暴力分析(超时)

翻转后子数组内部数组值不变,所以只需分析子数组的边界翻转后带来的损失和收益
遍历取最大值即可,注意分情况讨论

枚举所有左右边界
class Solution {
public:
    int maxValueAfterReverse(vector<int> &nums) {
         int res = 0;
         int n = nums.size();
         for(int i=0;i<n-1;i++)
            res = res + abs(nums[i]-nums[i+1]);
        int profit = 0;
        int gain,loss;
        int lbound,rbound,lchange,rchange;
        lchange = nums[0];
        for(int i=1;i<n-1;i++)//左边界去交换
        {
            rchange = nums[i];
            rbound = nums[i+1];
            gain = abs(lchange-rbound);
            loss = abs(rchange-rbound);
            profit = max(profit,gain-loss);
        }

        rchange = nums[n-1];//右边界去交换
        for(int i=1;i<n-1;i++){
            lchange = nums[i];
            lbound = nums[i-1];
            gain = abs(rchange-lbound);
            loss = abs(lchange-lbound);
            profit = max(profit,gain-loss); 
        }

        for(int i=1;i<n-2;i++){
            lbound = nums[i-1];
            lchange = nums[i];
            for(int j=i+1;j<n-1;j++){
                rchange = nums[j];
                rbound = nums[j+1];
                loss = abs(lbound-lchange) + abs(rbound-rchange);
                gain = abs(lbound-rchange) + abs(rbound-lchange);
                profit = max(profit,gain-loss);
            }
        }
        return res + profit;
    }
};

2. 优化(数学规律)

通过1可以发现该题就是最大化增益的过程,即最大化如下profit
profit = abs(lbound-rchange) + abs(rbound-lchange) - abs(lbound-lchange) - abs(rbound-rchange);
下面将对应四个值,简化成A,B,C,D
也就是profit = abs(A-C) + abs(B-D)-abs(A-B)-abs(C-D)
下面就是找规律时间
讨论AC、BD的大小情况,再讨论AB、CD的大小情况去掉绝对值,将结果必然小于等于0的去掉
可以看出来这里总共有16种情况,最后总结数学规律

class Solution {
public:
    int maxValueAfterReverse(vector<int> &nums) {
         int n = nums.size();
        int max_ = INT_MIN; int min_ = INT_MAX;
        int res = abs(nums[0]-nums[1]);
        int profit = 0;
        for(int i=1;i<n-1;i++){
            res = res + abs(nums[i]-nums[i+1]);//计算总数组值
            profit = max(profit,abs(nums[0]-nums[i+1])-abs(nums[i+1]-nums[i])); //左边界用于交换
            profit = max(profit,abs(nums[n-1]-nums[i-1])-abs(nums[i]-nums[i-1])); //右边界用于交换
        }
        for(int i=1;i<n;i++){
            max_ = max(max_,min(nums[i-1],nums[i]));//相邻数的最小值,最大化利润要求该值最大值
            min_ = min(min_,max(nums[i-1],nums[i]));//相邻数的最大值,最大化利润要求该值最小值
        }
        return res + max(profit,2*(max_-min_));
    }
};

3. 最终优化

class Solution {
public:
    int maxValueAfterReverse(vector<int> &nums) {
         int n = nums.size();
        int max_ = INT_MIN; int min_ = INT_MAX;
        int res = 0;
        int profit = 0;
        for(int i=1;i<n;i++){
            res = res + abs(nums[i]-nums[i-1]);//计算总数组值
            profit = max(profit,abs(nums[0]-nums[i])-abs(nums[i]-nums[i-1])); //左边界用于交换
            profit = max(profit,abs(nums[n-1]-nums[i-1])-abs(nums[i]-nums[i-1])); //右边界用于交换
            max_ = max(max_,min(nums[i-1],nums[i]));//相邻数的最小值,最大化利润要求该值最大值
            min_ = min(min_,max(nums[i-1],nums[i]));//相邻数的最大值,最大化利润要求该值最小值
        }
        return res + max(profit,2*(max_-min_));
    }
};
posted @ 2023-05-12 01:54  失控D大白兔  阅读(91)  评论(0)    收藏  举报