8.21 - hard - 80

410. Split Array Largest Sum

有两种解法:

  1. 按值二分: 左边界是array里的最大值,右边界是array的sum。按照贪心来做,a. 把array 从左边切割,b.尽量使得两刀之间的值靠近mid,但是小于mid,c. 最后会出现两种情况,一是可以把array切成超过m个subarray,说明mid太小了,否则说明mid太大了。
  2. DP:dp[s][j] 表示把 n[j]...n[L-1] 分成s份能获得的最小和,dp[s+1][i] = min{ max(dp[s][j], n[i]+...+n[j-1]) }, i+1 <= j <= L-s 从i到最后能分成s+1份的最小值就等于,j到最后能分成s份的最小值 和 i到j-1的和这两个值中比较大的值,再取最小,类似minmax,DP的写法可以用memory search感觉写起来要清爽一些。
DP的解法
class Solution(object):
    def splitArray(self, nums, m):
        """
        :type nums: List[int]
        :type m: int
        :rtype: int
        """
        sums = [0]*len(nums)
        sums[len(nums)-1] = nums[len(nums)-1] # sums 表示从某个index到最后一个点的subarray和
        for i in range(len(nums)-2, -1, -1):
            sums[i] = sums[i+1] + nums[i]
        
        memo = [[0]*(m+1) for _ in range(len(nums))]
        
        return self.search(nums, 0, m, sums, memo)
    
    def search(self, nums, start, m, sums, memo):
        if m == 1: #  如果只分成一个部分,从start到最后
            return sums[start]
        if memo[start][m] > 0:
            return memo[start][m]
        min_val = sys.maxint
        total = 0
        
        for i in range(start, len(nums)-m+1):
            total += nums[i]
            # total是从start到i这一段的和,这个与i+1到最后分成m-1份的最小值相比较,取其中的较大的值
            # 然后loop i,取这些值中比较小的值。
            min_val = min(max(total, self.search(nums, i + 1, m - 1, sums, memo)), min_val)
        
        memo[start][m] = min_val
        return min_val
二分法解法
class Solution(object):
    def splitArray(self, nums, m):
        """
        :type nums: List[int]
        :type m: int
        :rtype: int
        """
        max_value = max(nums)
        sum_value = sum(nums)
        if m == 1:
            return sum_value
        # binary search
        l = max_value
        r = sum_value
        while l + 1 < r:
            mid = (l + r)/ 2
            if self.valid(mid, nums, m):
                r = mid
            else:
                l = mid
        if self.valid(l, nums, m):
            return l
        else:
            return r
    
    def valid(self, target, nums, m):
        count = 1;
        total = 0;
        for num in nums:
            total += num
            if total > target:
                total = num
                count += 1
                if count > m:
                    return False
        return True
        

你可能感兴趣的:(8.21 - hard - 80)