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

文章目录

  • Partition Array for Maximum Sum 分隔数组以得到最大和
    • 问题描述:
    • 分析
    • 代码

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

问题描述:

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

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

分析

就是一个数组arr,对其计算和,可以将原始数组进行分割,分割成为若干的子数组,子数组的长度<=k,分割后的子数组的值都会变成该子数组中的最大值。
也就是说,应该存在一种分割,使得每个子数组都得到最大值,从而使得整个数组取的最大。
但是这样的分割是不确定的,长度可以是1,最大是k-1。
所以只能尝试传统的递归搜索,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)=maxj=max(ik,0)i1{DFS(j)+(ij)×maxp=j+1iarr[p]}
由于dfs的定义,所以可以将dfs(0)~dfs(k)的结果预处理,并作为边界。
最终的结果,就是dfs(n-1).
而整个dfs的时间复杂度是基于n的规模,时间复杂度很大,而中间又会出现非常多的重复,所以memo记忆化就可以上了。

既然可以通过dfs+memo递归回溯得到结果,那么正向的递推也可以。
f[i]表示下标i结尾的数组划分子数组后,可以得到的最大和。
f [ i ] = max ⁡ j = max ⁡ ( i − k , 0 ) i − 1 { f ( j ) + ( i − j ) × m x } f[i] = \max_{j=\max(i-k,0)}^{i-1} \{f(j)+ (i-j) \times mx \} f[i]=maxj=max(ik,0)i1{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(Nk)

空间复杂度: O(N)

Tag

Array Dynamic Programming

你可能感兴趣的:(数据结构与算法,算法,动态规划)