LeetCode 动态规划 任意子数组和的绝对值的最大值

任意子数组和的绝对值的最大值

给你一个整数数组 nums 。一个子数组 [numsl, numsl+1, …, numsr-1, numsr] 的 和的绝对值 为 abs(numsl + numsl+1 + … + numsr-1 + numsr) 。
请你找出 nums 中 和的绝对值 最大的任意子数组(可能为空),并返回该 最大值 。
abs(x) 定义如下:
如果 x 是负整数,那么 abs(x) = -x 。
如果 x 是非负整数,那么 abs(x) = x 。
示例 1:
输入:nums = [1,-3,2,3,-4]
输出:5
解释:子数组 [2,3] 和的绝对值最大,为 abs(2+3) = abs(5) = 5 。
示例 2:
输入:nums = [2,-5,1,-4,3,-2]
输出:8
解释:子数组 [-5,1,-4] 和的绝对值最大,为 abs(-5+1-4) = abs(-8) = 8 。
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104

题解

首先来一个错误的思路

错误思路

对于每一个数组的元素,它只有成为前面的子数组的一部分或者成为另一个新数组的开头这两种选择

只需要选这两种选择中执行后绝对值更大的就行了

错误原因

举个例子

数组[8,-2,-6,-1,-10]

显然最大和的绝对值子数组为-2,-6,-1,-10

但是依据上述思路,对于-2这个数据,加上前面的8之后的绝对值更大,我们就将8加上

但是加上8之后导致后面的计算就无法取到最大的子数组值

换句话说

最大的绝对值是最大的正或最小的负

上诉思路中,对于每一个元素我们都选择了最大的正或最小的负中的一个

这样就导致后面的数据进行选择的时候少了一种可能

所以不能按照当前数据与以前面数据结尾的子数组的绝对值的最大值进行比较从而得出结果的思路

因为对于绝对值是需要在最大的正与最小的负中选择的

以前面数据结尾的子数组的绝对值的最大值少了其中一种情况

求出的结果是不正确的

正确的思路应当是比较以前面数据结尾的子数组的最大值与最小值

判断是否加上最大或最小这两种情况之后选择其中绝对值最大的

正确思路

对于绝对值,我们可以求出子数组和的最大值以及最小值

再选择其中绝对值大的即可

对于求子数组的最大值

我们可以将问题拆分为

对于一个数据,它只有加入以前一个数据结尾的子数组或者不加入成为新的开头

如果以前一个数据结尾的子数组的和是负的,显然应当不加入成为新的开头

否则加入以前一个数据结尾的子数组

每一个数据选择后的最大值就是子数组的最大值

求最小值同理

最后选择其中绝对值大的

代码如下

int maxAbsoluteSum(int* nums, int numsSize) {
    int res=abs(nums[0]);
    int max=nums[0];
    int min=nums[0];
    for(int i=1;i<numsSize;i++)
    {
        if(max>0)
        {
            max+=nums[i];
        }
        else
        {
            max=nums[i];
        }
        if(min<0)
        {
            min+=nums[i];
        }
        else
        {
            min=nums[i];
        }
        int n=max>-min?max:-min;
        if(n>res)
        {
            res=n;
        }
    }
    return res;
}
### 关于LeetCode Problem 2264 对于编号为2264的问题,即最大重叠区间数量(Maximum Width of Binary Tree),实际上该描述并不完全匹配问题2264。根据最新的LeetCode题目列表,编号2264对应的是“字符串中的最大数字”(Largest Number After Digit Swaps by Parity)[^1]。 此问题要求给定一个整数`num`,返回通过交换任意次数的奇偶位置上的数字所能得到的最大整数值。注意这里的奇偶是指索引位置而非数字本身的奇偶性。例如,在十进制表示下,最右边的位置视为索引0(偶数),其左边紧邻的位置则为索引1(奇数),以此类推。 #### 解决方案概述 为了实现这一目标,可以采用如下策略: - 将输入整数转换成字符数组以便逐位处理。 - 创建两个优先队列分别用于存储位于奇数偶数索引处的数字。 - 对原数组遍历一次填充上述两个优先队列,并保持各自内部降序排列。 - 再次遍历时从这两个队列取出顶部元素按原始顺序重新构建结果字符串,确保每次取自相应类型的索引对应的堆顶元素。 - 最终将重组后的字符序列转回整型作为输出。 下面是具体的C++代码实现方式: ```cpp class Solution { public: int largestInteger(int num) { string s = to_string(abs(num)); // 转换成绝对值并转化为字符串形式 priority_queue<int> odd, even; for(char c : s){ if((c-'0')%2==0) even.push(c-'0'); // 偶数入even队列 else odd.push(c-'0'); // 奇数入odd队列 } string res = ""; for(auto& c:s){ if ((c - '0') % 2 == 0) { res += to_string(even.top()); even.pop(); } else { res += to_string(odd.top()); odd.pop(); } } return stoi(res)*(num>=0?1:-1); } }; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

软行

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

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

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

打赏作者

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

抵扣说明:

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

余额充值