原本有一个贪心算法的思路,仔细推敲后发现有bug。
根据官方题解:有动态规划和二分贪心两种解决思路。
class Solution { public: int splitArray(vector<int>& nums, int m) { //初始化sum数组 vector<long> temp(nums.size(),0); vector<vector<long>> sums(nums.size(),temp); for(int i=0;i<nums.size();i++){ sums[i][i]=nums[i]; for(int j=i+1;j<nums.size();j++){ sums[i][j]=sums[i][j-1]+nums[j]; } } vector<long> temp2(m+1,-1); vector<vector<long>> f(nums.size()+1,temp2); for(int i=0;i<=nums.size();i++){f[i][0]=0;} for(int j=0;j<=m;j++){ for(int i=j;i<=nums.size();i++){ for(int m=j-1;m>=0&&m<=i-1;m++){ if(f[i][j]==-1){ f[i][j]=max(f[m][j-1],sums[m][i-1]);printf("??f[%d][%d]=%d\n",i,j,f[i][j]);} else if(j-1>0) f[i][j]=min(f[i][j],max(f[m][j-1],sums[m][i-1])); } printf("check%d %d %d\n",i,j,f[i][j]); } } return f[nums.size()][m]; } }; /* 官方题解思路1:动态规划 f[i][j]存储,前i(0...i-1)个元素被分成j个子数组,j个子数组各自和的最大值的最小值。 状态转移方程:f[i][j]=min{max(f[m][j-1],sum(m,i))},m=j-1,j,j+1,...i-1 可以提前先把所有的sum(a,b)存到一个辅助数组中供重复使用 初始状态:f[n][0]=0; 我的思路 切分成m个非空连续子数组。先把所有数组元素看成n个叶子结点排成一排,两个节点刻意合并用它们的和代替原来的两个节点,连续合并n-m次,剩下m棵子树,他们的根节点 我想到用贪心的思路,每次合并的两个节点,是所有可能合并节点和最小的。 证明:在存在i个数组的情况下, 我的思路有漏洞!!!! */
时间复杂度:n^2*m
空间复杂度:n^2可以降到n,用减法!
二分+贪心待实现。
本题可能还需要复习+练习
原文:https://www.cnblogs.com/BoysCryToo/p/13378584.html