[LeetCode] 548. Split Array with Equal Sum 分割数组成和相同的子数组
Given an array with n integers, you need to find if there are triplets (i, j, k) which satisfies following conditions:
- 0 < i, i + 1 < j, j + 1 < k < n - 1
- Sum of subarrays (0, i - 1), (i + 1, j - 1), (j + 1, k - 1) and (k + 1, n - 1) should be equal.
where we define that subarray (L, R) represents a slice of the original array starting from the element indexed L to the element indexed R.
Example:
Input: [1,2,1,2,1,2,1]
Output: True
Explanation:
i = 1, j = 3, k = 5.
sum(0, i - 1) = sum(0, 0) = 1
sum(i + 1, j - 1) = sum(2, 2) = 1
sum(j + 1, k - 1) = sum(4, 4) = 1
sum(k + 1, n - 1) = sum(6, 6) = 1
Note:
- 1 <= n <= 2000.
- Elements in the given array will be in range [-1,000,000, 1,000,000].
给一个数组,找出三个位置,使得数组被分为四段,使得每段之和相等,问存不存在这样的三个位置,注意三个位置上的数字不属于任何一段。
解法1: 暴力法,那就是三重循环,时间复杂度是O(n^3),空间复杂度是O(n)。过不了大数据, TLE。
解法2: 采用空间换时间,从中间进行分割,然后在前半部分进行搜索,看看是不是可以找到和相同的划分,如果找到了,就将和加入哈希表中;然后再在后半部分进行搜索,如果找到了和相同的划分并且该和也存在于哈希表中,这说明找到了合适的i,j,k,可以将数组划分为和相同的四个部分,返回true。这样时间复杂度就降低成了O(n^2)。
解法3: 建立一个长度为数组长度的sum[i],然后计算出每一个位置的它前面所有数字的和,这样就避免了以后大量的重复计算和的运算。然后计算i-j是否有满足1-i的和等于i-j, 有的话存到set里,避免重复计算。然后在计算位置k,是否也等于之前set里的值,如果有就返回True.
解法4: 用数组sums记录前n项和,在用字典idxs统计sums元素对应的下标列表,根据sums和idxs枚举满足(0, i - 1) == (i + 1, j - 1)条件的i,j。利用字典jlist记录子数组和对应的j值列表。最后遍历k,枚举jlist中子数组和(k + 1, n - 1)对应的j值,然后判断是否存在 (j + 1, k - 1) 与 (k + 1, n - 1) 相等
Java: 暴力, TLE
public class Solution { public int sum(int[] nums, int l, int r) {
int summ = 0;
for (int i = l; i < r; i++)
summ += nums[i];
return summ;
} public boolean splitArray(int[] nums) {
if (nums.length < 7)
return false;
for (int i = 1; i < nums.length - 5; i++) {
int sum1 = sum(nums, 0, i);
for (int j = i + 2; j < nums.length - 3; j++) {
int sum2 = sum(nums, i + 1, j);
for (int k = j + 2; k < nums.length - 1; k++) {
int sum3 = sum(nums, j + 1, k);
int sum4 = sum(nums, k + 1, nums.length);
if (sum1 == sum2 && sum3 == sum4 && sum2 == sum4)
return true;
}
}
}
return false;
}
}
Java: 暴力,TLE
public class Solution {
public boolean splitArray(int[] nums) {
if (nums.length < 7)
return false;
int[] sum = new int[nums.length];
sum[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
sum[i] = sum[i - 1] + nums[i];
}
for (int i = 1; i < nums.length - 5; i++) {
int sum1 = sum[i - 1];
for (int j = i + 2; j < nums.length - 3; j++) {
int sum2 = sum[j - 1] - sum[i];
for (int k = j + 2; k < nums.length - 1; k++) {
int sum3 = sum[k - 1] - sum[j];
int sum4 = sum[nums.length - 1] - sum[k];
if (sum1 == sum2 && sum3 == sum4 && sum2 == sum4)
return true;
}
}
}
return false;
}
}
Java: TLE
public class Solution {
public boolean splitArray(int[] nums) {
if (nums.length < 7)
return false; int[] sum = new int[nums.length];
sum[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
sum[i] = sum[i - 1] + nums[i];
}
for (int i = 1; i < nums.length - 5; i++) {
int sum1 = sum[i - 1];
for (int j = i + 2; j < nums.length - 3; j++) {
int sum2 = sum[j - 1] - sum[i];
if (sum1 != sum2)
continue;
for (int k = j + 2; k < nums.length - 1; k++) {
int sum3 = sum[k - 1] - sum[j];
int sum4 = sum[nums.length - 1] - sum[k];
if (sum3 == sum4 && sum2 == sum4)
return true;
}
}
}
return false;
}
}
Java: Accepted
public class Solution {
public boolean splitArray(int[] nums) {
if (nums.length < 7)
return false;
int[] sum = new int[nums.length];
sum[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
sum[i] = sum[i - 1] + nums[i];
}
for (int j = 3; j < nums.length - 3; j++) {
HashSet < Integer > set = new HashSet < > ();
for (int i = 1; i < j - 1; i++) {
if (sum[i - 1] == sum[j - 1] - sum[i])
set.add(sum[i - 1]);
}
for (int k = j + 2; k < nums.length - 1; k++) {
if (sum[nums.length - 1] - sum[k] == sum[k - 1] - sum[j] && set.contains(sum[k - 1] - sum[j]))
return true;
}
}
return false;
}
}
Python:
# Time: O(n^2)
# Space: O(n) class Solution(object):
def splitArray(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
if len(nums) < 7:
return False accumulated_sum = [0] * len(nums)
accumulated_sum[0] = nums[0]
for i in xrange(1, len(nums)):
accumulated_sum[i] = accumulated_sum[i-1] + nums[i]
for j in xrange(3, len(nums)-3):
lookup = set()
for i in xrange(1, j-1):
if accumulated_sum[i-1] == accumulated_sum[j-1] - accumulated_sum[i]:
lookup.add(accumulated_sum[i-1])
for k in xrange(j+2, len(nums)-1):
if accumulated_sum[-1] - accumulated_sum[k] == accumulated_sum[k-1] - accumulated_sum[j] and \
accumulated_sum[k - 1] - accumulated_sum[j] in lookup:
return True
return False
Python:
class Solution(object):
def splitArray(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
size = len(nums)
sums = [0] * (size + 1)
for x in range(size):
sums[x + 1] += sums[x] + nums[x] idxs = collections.defaultdict(list)
for x in range(size):
idxs[sums[x + 1]].append(x) jlist = collections.defaultdict(list)
for i in range(1, size):
for j in idxs[2 * sums[i] + nums[i]]:
if i < j < size:
jlist[sums[i]].append(j + 1) for k in range(size - 2, 0, -1):
for j in jlist[sums[size] - sums[k + 1]]:
if j + 1 > k: continue
if sums[k] - sums[j + 1] == sums[size] - sums[k + 1]:
return True
return False
C++:
class Solution {
public:
bool splitArray(vector<int>& nums) {
if (nums.size() < 7) return false;
int n = nums.size();
vector<int> sums = nums;
for (int i = 1; i < n; ++i) {
sums[i] = sums[i - 1] + nums[i];
}
for (int j = 3; j < n - 3; ++j) {
unordered_set<int> s;
for (int i = 1; i < j - 1; ++i) {
if (sums[i - 1] == (sums[j - 1] - sums[i])) {
s.insert(sums[i - 1]);
}
}
for (int k = j + 1; k < n - 1; ++k) {
int s3 = sums[k - 1] - sums[j], s4 = sums[n - 1] - sums[k];
if (s3 == s4 && s.count(s3)) return true;
}
}
return false;
}
};
C++:
class Solution {
public:
bool splitArray(vector<int>& nums) {
if (nums.size() < 7) return false;
int n = nums.size(), target = 0;
int sum = accumulate(nums.begin(), nums.end(), 0);
for (int i = 1; i < n - 5; ++i) {
if (i != 1 && nums[i] == 0 && nums[i - 1] == 0) continue;
target += nums[i - 1];
if (helper(nums, target, sum - target - nums[i], i + 1, 1)) {
return true;
}
}
return false;
}
bool helper(vector<int>& nums, int target, int sum, int start, int cnt) {
if (cnt == 3) return sum == target;
int curSum = 0, n = nums.size();
for (int i = start + 1; i < n + 2 * cnt - 5; ++i) {
curSum += nums[i - 1];
if (curSum == target && helper(nums, target, sum - curSum - nums[i], i + 1, cnt + 1)) {
return true;
}
}
return false;
}
C++: 暴力+优化
class Solution {
public:
bool splitArray(vector<int>& nums) {
int n = nums.size();
vector<int> sums = nums;
for (int i = 1; i < n; ++i) {
sums[i] = sums[i - 1] + nums[i];
}
for (int i = 1; i <= n - 5; ++i) {
if (i != 1 && nums[i] == 0 && nums[i - 1] == 0) continue;
for (int j = i + 2; j <= n - 3; ++j) {
if (sums[i - 1] != (sums[j - 1] - sums[i])) continue;
for (int k = j + 2; k <= n - 1; ++k) {
int sum3 = sums[k - 1] - sums[j];
int sum4 = sums[n - 1] - sums[k];
if (sum3 == sum4 && sum3 == sums[i - 1]) {
return true;
}
}
}
}
return false;
}
};
类似题目:
Split an array into two equal Sum subarrays
All LeetCode Questions List 题目汇总
[LeetCode] 548. Split Array with Equal Sum 分割数组成和相同的子数组的更多相关文章
- LeetCode 548. Split Array with Equal Sum (分割数组使得子数组的和都相同)$
Given an array with n integers, you need to find if there are triplets (i, j, k) which satisfies fol ...
- [LeetCode] Split Array with Equal Sum 分割数组成和相同的子数组
Given an array with n integers, you need to find if there are triplets (i, j, k) which satisfies fol ...
- 【LeetCode】548. Split Array with Equal Sum 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力 日期 题目地址:https://leetcode ...
- 【LeetCode Weekly Contest 26 Q4】Split Array with Equal Sum
[题目链接]:https://leetcode.com/contest/leetcode-weekly-contest-26/problems/split-array-with-equal-sum/ ...
- leetcode548 Split Array with Equal Sum
思路: 使用哈希表降低复杂度.具体来说: 枚举j: 枚举i,如果sum[i - 1] == sum[j - 1] - sum[i],就用哈希表把sum[i - 1]记录下来: 枚举k,如果sum[k ...
- [LeetCode] Split Array With Same Average 分割数组成相同平均值的小数组
In a given integer array A, we must move every element of A to either list B or list C. (B and C ini ...
- [LeetCode] 410. Split Array Largest Sum 分割数组的最大值
Given an array which consists of non-negative integers and an integer m, you can split the array int ...
- [LeetCode] 805. Split Array With Same Average 用相同均值拆分数组
In a given integer array A, we must move every element of A to either list B or list C. (B and C ini ...
- [LeetCode] 915. Partition Array into Disjoint Intervals 分割数组为不相交的区间
Given an array A, partition it into two (contiguous) subarrays left and right so that: Every element ...
随机推荐
- Centos7-新增硬盘挂载
查看现有硬盘情况 df -h fdisk -l 查看新硬盘 ls /dev/sdb 具体操作 fdisk /dev/sdb m n #添加一个新的分区 p #创建主分区 w #保存并退出 partpr ...
- 20199301《Linux内核原理与分析》第十一周作业
Linux Capability探索实验 一.实验描述 本实验中,将感受到linux capability功能在访问控制上的优势,掌握使用Capability达到遵守最小权限原则的目的,并分析linu ...
- ZOJ - 3157:Weapon (几何 逆序对)
pro:给定平面上N条直线,保证没有直线和Y轴平行. 求有多少交点的X坐标落在(L,R)开区间之间,注意在x=L或者R处的不算. sol:求出每条直线与L和R的交点,如果A直线和B直线在(L,R)相交 ...
- xshell连接不上阿里云服务器Could not connect to 'ip' (port 22): Connection failed.解决过程
记一次xshell阿里云服务器突然连接不上的解决办法: 1, 确认阿里云服务器安全组出入都有22,百度出来都说的这个和ip拦截设置,以防万一都设置了:但楼主设置后,还是连不上服务器: 只好下一步 2, ...
- Markdwon入门2
插入表情 这里是指广义的表情包,包括表情.物体.动物等. :+1: :smile: :s :scream: :kissing_heart: :yum: :cry: :blush: :frog: :co ...
- WinDbg常用命令系列---|(进程状态)
|(进程状态) 简介 (|) 命令显示指定进程的状态或当前正在调试你的所有进程. 使用形式 | Process 参数 Process 指定要显示的进程. 如果省略此参数,将显示所有正在调试的进程. 支 ...
- 使用WinDbg调试入门(内核模式)
windbg是一个内核模式和用户模式调试器,包含在Windows调试工具中.这里我们提供了一些实践练习,可以帮助您开始使用windbg作为内核模式调试器. 设置内核模式调试 内核模式调试环境通常有两台 ...
- centos 较新版本kernel安装方法
有时因为系统内核的bug 我们必须要安装新版本的kernel 来解决问题,有几种方法 源码编译 使用编译好的包 使用包的方式比较方便,同时一些依赖的问题可以自动帮助我们处理 添加yum 源 rpm - ...
- edgedb 开发环境运行
以下是一篇来自官方的edgedb 开发环境搭建说明,实际上我以前自己也摸索过一个,基本方法一样,一些是官方的做一个 简单的记录 预备工具 GNU make version 3.80 or newer; ...
- Comet OJ 2019 夏季欢乐赛题解
Comet OJ 2019 夏季欢乐赛题解 我是来骗访问量的 A 完全k叉树 \(n\)个点的完全k叉树的直径. 直接做 B 距离产生美 直接做 C 烤面包片 \(n!!!\mod p\) 显然\(n ...