龙空技术网

leetcode1712_go_将数组分成三个子数组的方案数

每天都AC 26

前言:

而今姐妹们对“一个数组分成多个数组”都比较珍视,小伙伴们都需要了解一些“一个数组分成多个数组”的相关内容。那么小编同时在网摘上收集了一些关于“一个数组分成多个数组””的相关内容,希望我们能喜欢,咱们快快来学习一下吧!

题目

我们称一个分割整数数组的方案是 好的 ,当它满足:

数组被分成三个 非空 连续子数组,从左至右分别命名为 left , mid , right 。

left 中元素和小于等于 mid 中元素和,mid 中元素和小于等于 right 中元素和。

给你一个 非负 整数数组 nums ,请你返回 好的 分割 nums 方案数目。

由于答案可能会很大,请你将结果对 109 + 7 取余后返回。

示例 1:输入:nums = [1,1,1] 输出:1

解释:唯一一种好的分割方案是将 nums 分成 [1] [1] [1] 。

示例 2:输入:nums = [1,2,2,2,5,0] 输出:3

解释:nums 总共有 3 种好的分割方案:

[1] [2] [2,2,5,0]

[1] [2,2] [2,5,0]

[1,2] [2,2] [5,0]

示例 3:输入:nums = [3,2,1] 输出:0

解释:没有好的分割方案。

提示:3 <= nums.length <= 105

0 <= nums[i] <= 104

解题思路分析

1、前缀和+双指针;时间复杂度O(n),空间复杂度O(n)

func waysToSplit(nums []int) int {	res := 0	n := len(nums)	arr := make([]int, n+1)	for i := 0; i < n; i++ {		arr[i+1] = arr[i] + nums[i]	}	left, right := 2, 2	for i := 1; i <= n-1; i++ {		first := arr[i] // 第1个数		left = max(left, i+1)		right = max(right, i+1)		for left <= n-1 && arr[left]-first < first { // 找到第一个满足的中间数组左边坐标			left++		}		for right <= n-1 && arr[right]-first <= arr[n]-arr[right] {			right++		}		if left <= right {			res = (res + right - left) % 1000000007		}	}	return res % 1000000007}func max(a, b int) int {	if a > b {		return a	}	return b}

2、前缀和+二分查找;时间复杂度O(nlog(n)),空间复杂度O(n)

func waysToSplit(nums []int) int {	res := 0	n := len(nums)	arr := make([]int, n+1)	for i := 0; i < n; i++ {		arr[i+1] = arr[i] + nums[i]	}	for i := 1; i <= n-1; i++ {		first := arr[i] // 第1个数		if first*3 > arr[n] {			break		}		left, right := i+1, n-1		for left <= right {			mid := left + (right-left)/2			if arr[n]-arr[mid] < arr[mid]-first {				right = mid - 1			} else {				left = mid + 1			}		}		b := left		left, right = i+1, n-1		for left <= right {			mid := left + (right-left)/2			if arr[mid]-first < first {				left = mid + 1			} else {				right = mid - 1			}		}		a := left		res = (res + b - a) % 1000000007	}	return res % 1000000007}
总结

Medium题目,暴力法容易超时,借助前缀和,可以使用双指针或者二分查找计算

标签: #一个数组分成多个数组 #将一个数组分成多个数组