3496. 最大化配对删除后的得分 🔒

English Version

题目描述

给定一个整数数组 nums。当数组中元素超过两个时,你 必须 重复执行以下操作中的一个:

  • 删除最前面的两个元素。
  • 删除最后面的两个元素。
  • 删除第一和最后一个元素。

对于每次操作,将移除的元素之和加到你的总分上。

返回你可以达到的 最高 分数。

 

示例 1:

输入:nums = [2,4,1]

输出:6

解释:

可能的操作有:

  • 删除最前面的两个元素 (2 + 4) = 6。剩余的数组是 [1]
  • 删除最后面的两个元素 (4 + 1) = 5。剩余的数组是 [2]
  • 删除第一个和最后一个元素 (2 + 1) = 3。剩余的数组是 [4]

通过删除最前面的两个元素可以得到最高分,因此最终分数是 6。

示例 2:

输入:nums = [5,-1,4,2]

输出:7

解释:

可能的操作是:

  • 删除第一个和最后一个元素 (5 + 2) = 7。剩余的数组是 [-1, 4]
  • 删除最前面的两个元素 (5 + -1) = 4。剩余的数组是 [4, 2]
  • 删除最后面的两个元素 (4 + 2) = 6。剩余的数组是 [5, -1]

通过删除第一个和最后一个元素可以得到最高分,因此最终分数是 7。

 

提示:

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

解法

方法一:逆向思维

根据题目描述,每次操作会移除掉端点的两个元素。因此,当元素个数为奇数时,最终会剩下 1 个元素;当元素个数为偶数时,最终会剩下数组中的连续两个元素。

为了使得删除后的得分最大化,我们应该使得剩下的元素最小。

因此,如果数组 $\textit{nums}$ 元素个数为奇数,那么答案就是数组 $\textit{nums}$ 所有元素的总和 $s$,减去数组 $\textit{nums}$ 中的最小值 $\textit{mi}$;如果数组 $\textit{nums}$ 元素个数为偶数,那么答案就是数组 $\textit{nums}$ 所有元素的总和 $s$,减去数组连续两个元素之和的最小值。

时间复杂度 $O(n)$,其中 $n$ 是数组 $\textit{nums}$ 的长度。空间复杂度 $O(1)$。

Python3

class Solution:
    def maxScore(self, nums: List[int]) -> int:
        s = sum(nums)
        if len(nums) & 1:
            return s - min(nums)
        return s - min(a + b for a, b in pairwise(nums))

Java

class Solution {
    public int maxScore(int[] nums) {
        final int inf = 1 << 30;
        int n = nums.length;
        int s = 0, mi = inf;
        int t = inf;
        for (int i = 0; i < n; ++i) {
            s += nums[i];
            mi = Math.min(mi, nums[i]);
            if (i + 1 < n) {
                t = Math.min(t, nums[i] + nums[i + 1]);
            }
        }
        if (n % 2 == 1) {
            return s - mi;
        }
        return s - t;
    }
}

C++

class Solution {
public:
    int maxScore(vector<int>& nums) {
        const int inf = 1 << 30;
        int n = nums.size();
        int s = 0, mi = inf;
        int t = inf;
        for (int i = 0; i < n; ++i) {
            s += nums[i];
            mi = min(mi, nums[i]);
            if (i + 1 < n) {
                t = min(t, nums[i] + nums[i + 1]);
            }
        }
        if (n % 2 == 1) {
            return s - mi;
        }
        return s - t;
    }
};

Go

func maxScore(nums []int) int {
	const inf = 1 << 30
	n := len(nums)
	s, mi, t := 0, inf, inf
	for i, x := range nums {
		s += x
		mi = min(mi, x)
		if i+1 < n {
			t = min(t, x+nums[i+1])
		}
	}
	if n%2 == 1 {
		return s - mi
	}
	return s - t
}

TypeScript

function maxScore(nums: number[]): number {
    const inf = Infinity;
    const n = nums.length;
    let [s, mi, t] = [0, inf, inf];
    for (let i = 0; i < n; ++i) {
        s += nums[i];
        mi = Math.min(mi, nums[i]);
        if (i + 1 < n) {
            t = Math.min(t, nums[i] + nums[i + 1]);
        }
    }
    return n % 2 ? s - mi : s - t;
}