【算法】Partition Array for Maximum Sum 分隔数组以得到最大和

文章讨论了一种数组处理问题,要求将数组分割成长度不超过k的子数组,使每个子数组变为最大值。通过分析,提出了使用动态规划和记忆化搜索的方法,以O(Nk)的时间复杂度和O(N)的空间复杂度找到最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Partition Array for Maximum Sum 分隔数组以得到最大和

问题描述:

给你一个整数数组 arr,请你将该数组分隔为长度 最多 为 k 的一些(连续)子数组。分隔完成后,每个子数组的中的所有值都会变为该子数组中的最大值。

arr.length 范围[1,500],arr[i]范围[0,10^9] ,k范围[1,arr.length]

分析

就是一个数组arr,对其计算和,可以将原始数组进行分割,分割成为若干的子数组,子数组的长度 l e n g t h < = k length<=k length<=k,分割后的子数组的值都会变成该子数组中的最大值

也就是说,应该存在一种分割,使得每个子数组都得到最大值,从而使得整个数组取的最大。

但是这样的分割是不确定的,长度可以是 1 1 1,最大是 k − 1 k-1 k1,所以只能尝试传统的递归搜索, d f s ( i ) 表示以下标 i 为结尾时可以得到的最大和 dfs(i) 表示以下标i为结尾时可以得到的最大和 dfs(i)表示以下标i为结尾时可以得到的最大和
D F S ( i ) = max ⁡ j = max ⁡ ( i − k , 0 ) i − 1 { D F S ( j ) + ( i − j ) × max ⁡ p = j + 1 i a r r [ p ] } DFS(i)= \max_{j=\max(i-k,0)}^{i-1} \{DFS(j)+ (i-j) \times \max_{p=j+1}^{i}arr[p] \} DFS(i)=j=max(ik,0)maxi1{DFS(j)+(ij)×p=j+1maxiarr[p]}

由于 d f s dfs dfs的定义,所以可以将 d f s ( 0 ) → d f s ( k ) dfs(0)\rightarrow dfs(k) dfs(0)dfs(k)的结果预处理,并作为边界。

那么最终的结果,就是 d f s ( n − 1 ) dfs(n-1) dfs(n1).

而整个dfs的时间复杂度是基于 n n n的规模,时间复杂度很大,而中间又会出现非常多的重复,所以memo记忆化就可以上了。

既然可以通过 d f s + m e m o dfs+memo dfs+memo递归回溯得到结果,那么正向的递推也可以。

f [ i ] 表示下标 i 结尾的数组划分子数组后,可以得到的最大和 f[i]表示下标i结尾的数组划分子数组后,可以得到的最大和 f[i]表示下标i结尾的数组划分子数组后,可以得到的最大和

状态转移方程

f [ i ] = max ⁡ j = max ⁡ ( i − k , 0 ) i − 1 { f ( j ) + ( i − j ) × m x } m x 表示 a r r [ j + 1 ] → a r r [ i ] 的最大值。 f[i] = \max_{j=\max(i-k,0)}^{i-1} \{f(j)+ (i-j) \times mx \}\\ mx表示arr[j+1]\rightarrow arr[i]的最大值。 f[i]=j=max(ik,0)maxi1{f(j)+(ij)×mx}mx表示arr[j+1]arr[i]的最大值。
$$
丐版方程:f[i] =max( f[j] + (i-j)*mx ) j<=i-1&&j>=i-k

代码

public int maxSumAfterPartitioning(int[] arr, int k) {
        int n = arr.length;
        int[] d = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            int maxValue = arr[i - 1];
            for (int j = i - 1; j >= 0 && j >= i - k; j--) {
                d[i] = Math.max(d[i], d[j] + maxValue * (i - j));
                if (j > 0) {
                    maxValue = Math.max(maxValue, arr[j - 1]);
                }
            }
        }
        return d[n];
    }
 

时间复杂度 O ( N k ) O(Nk) O(Nk)

空间复杂度: O ( N ) O(N) O(N)

Tag

Array Dynamic Programming

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Eric.Cui

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

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

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

打赏作者

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

抵扣说明:

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

余额充值