leetcode-410. Split Array Largest Sum

题目:

Given an array which consists of non-negative integers and an integer m, you can split the array into m non-empty continuous subarrays. Write an algorithm to minimize the largest sum among these m subarrays.

Note:
Given m satisfies the following constraint: 1 ≤ m ≤ length(nums) ≤ 14,000.

Examples:

Input:
nums = [7,2,5,10,8]
m = 2

Output:
18

Explanation:
There are four ways to split nums into two subarrays.
The best way is to split it into [7,2,5] and [10,8],
where the largest sum among the two subarrays is only 18.
简单意思就是:给你一个含有n个元素的数组,让你把这数组划分成m段,那么每个段的所有元素就有一个sum,那么一次划分就会有一个最大的和(largest_sum),现在就是让你

求这个largest_sum的最小值!!!

方法一:

刚开始拿到这个题目,看到它的提示是动态规划,就一直想,就是想不出来后来在网上找到了大神们都用二分查找算法,但是这些博客没有对算法的思路有个详细的介绍,本文

就二分查找方法给出自己的理解!!

代码(模仿大神们的思想写的):

class Solution {
public:
	bool is_reach(vector& arr, int m, long target_sum){
		long cur_sum = arr[0];
		int sections = 1;
		for (int i = 1; i < arr.size(); ++i){
			cur_sum += arr[i];
			if (cur_sum > target_sum){
				++sections;
				cur_sum = arr[i];
			}
		}
		if (sections > m)return false;//如果段计数器值大于m,假设题目要求m=3,而我们求得的段的大小为4,
		return true;
	}

	int splitArray(vector& arr, int m) {
		int n = arr.size();
		long low = arr[0], high = arr[0];
		for (int i = 1; i < n; ++i){
			low = max(low, long(arr[i]));//数组的单个最大元素
			high += arr[i];//数组的所有元素
		}
		int res = 0;
		while (low < high){
			long mid = (low + high) / 2;
			if (is_reach(arr, m, mid)){
				high = mid;
				res = mid;
			}
			else
				low = mid + 1;
		}
		return low;
	}
};


 
  

Submission Result: Accepted  More Details 

Next challenges:  (M) Unique Binary Search Trees  (E) Closest Binary Search Tree Value  (M) Count Numbers with Unique Digits

Share your acceptance!

解析(leetcode上大神给的解释):

1.我们可以这样对待数组,我们将数组分成每段小于或等于target_num的小组,那么每个小组的和肯定小于或等于target_sum,如果此时我们得到的分段数目小于或等于m,

那么确定最大子段和小于或等于target_sum,否则,最大子段和的最小值一定大于target_sum;

2. 在设计的时候一定要注意: 如果写成high=mid和low=mid的模式,则有可能陷入死循环的可能,因为我们最后low,mid和high的指针的转态如下图所示:

leetcode-410. Split Array Largest Sum_第1张图片

如果is_reach传回的值是true,那么执行low=mid,那么会陷入死循环!!!!

方法二:

利用动态规划思想:

版本1:

int splitArray1(vectornums, int m){
	int L = nums.size();
	int *S = new int[L + 1];
	S[0] = 0;
	for (int i = 0; i

Submission Result: Accepted  More Details 

Next challenges:  (H) Regular Expression Matching  (M) Search Insert Position  (M) Range Sum Query 2D - Immutable

版本2:

class Solution {
public:
	int splitArray(vector& nums, int m) {
		int size = nums.size();
		vectorrow(size,0);
		vector>re;
		for (int i = 0; i <= m; i++)re.push_back(row);//二维数组
		//将数组分成1段的情况
		int sum = 0;
		for (int j = 0; j < size; j++){
			sum += nums[j];
			re[1][j] = sum;
		}

		//填表
		int temp, now;
		for (int i = 2; i <= m;i++){//i表示要分成的段数
			for (int j = i - 1; j < size;j++){
				temp = INT_MAX;
				for (int k = i - 2; k <= j - 1; k++){
					//re[i][j]表示将数组索引从0到j的元素分成i段
					now = max(re[i-1][k],re[1][j]-re[1][k]);
					if (now<=temp)temp = now;
				}
				re[i][j] = temp;
			}
		}
		return re[m][size - 1];
	}
};
结果:

Status: 

Time Limit Exceeded

Submitted:  2 minutes ago


这个说明思想没有问题的,但是时间复杂度较高,运行超时,还要进一步优化!!!

算法思想:

re[s][j]:表示数组元素下标从0到j分成s段的结果;

re[s+1][j]:表示数组元素下标从0到j分成s+1段的结果,那么re[s+1][j]=min{max(d[s,k],a[k+1]+a[k+2]+....+a[j])},其中,s-2<=k<=j-1(见代码).

你可能感兴趣的:(c++,410.,Split,Array,Lar,Leetcode)