[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 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].
class Solution {
public:
bool splitArray(vector<int>& nums) {
if (nums.size() < ) return false;
int n = nums.size();
vector<int> sums = nums;
for (int i = ; i < n; ++i) {
sums[i] = sums[i - ] + nums[i];
}
for (int j = ; j < n - ; ++j) {
unordered_set<int> s;
for (int i = ; i < j - ; ++i) {
if (sums[i - ] == (sums[j - ] - sums[i])) {
s.insert(sums[i - ]);
}
}
for (int k = j + ; k < n - ; ++k) {
int s3 = sums[k - ] - sums[j], s4 = sums[n - ] - sums[k];
if (s3 == s4 && s.count(s3)) return true;
}
}
return false;
}
};
下面这种解法是递归的暴力破解写法,刚开始博主还纳闷了,为啥博主之前写的迭代形式的暴力破解过不了OJ,而这个递归版本的确能通过呢,仔细研究了一下,发现这种解法有两个地方做了优化。第一个优化是在for循环里面,如果i不等于1,且当前数字和之前数字均为0,那么跳过这个位置,因为加上0也不会对target有任何影响,那为什么要加上i不等于1的判断呢,因为输入数组如果是七个0,那么实际上应该返回true的,而如果没有i != 1这个条件限制,后面的代码均不会得到执行,那么就直接返回false了,是不对的。第二个优化的地方是在递归函数里面,只有当curSum等于target了,才进一步调用递归函数,这样就相当于做了剪枝处理,减少了大量的不必要的运算,这可能就是其可以通过OJ的原因吧。
再来说下子函数for循环的终止条件 i < n - 5 + 2*cnt 是怎么得来的,是的,这块的确是个优化,因为i的位置是题目中三个分割点i,j,k的位置,所以其分别有自己可以取值的范围,由于只有三个分割点,所以cnt的取值可以是0,1,2。
-> 当cnt=0时,说明是第一个分割点,那么i < n - 5,表示后面必须最少要留5个数字,因为分割点本身的数字不记入子数组之和,那么所留的五个数字为:数字,第二个分割点,数字,第三个分割点,数字。
-> 当cnt=1时,说明是第二个分割点,那么i < n - 3,表示后面必须最少要留3个数字,因为分割点本身的数字不记入子数组之和,那么所留的三个数字为:数字,第三个分割点,数字。
-> 当cnt=2时,说明是第三个分割点,那么i < n - 1,表示后面必须最少要留1个数字,因为分割点本身的数字不记入子数组之和,那么所留的一个数字为:数字。
解法二:
class Solution {
public:
bool splitArray(vector<int>& nums) {
if (nums.size() < ) return false;
int n = nums.size(), target = ;
int sum = accumulate(nums.begin(), nums.end(), );
for (int i = ; i < n - ; ++i) {
if (i != && nums[i] == && nums[i - ] == ) continue;
target += nums[i - ];
if (helper(nums, target, sum - target - nums[i], i + , )) {
return true;
}
}
return false;
}
bool helper(vector<int>& nums, int target, int sum, int start, int cnt) {
if (cnt == ) return sum == target;
int curSum = , n = nums.size();
for (int i = start + ; i < n - + * cnt; ++i) {
curSum += nums[i - ];
if (curSum == target && helper(nums, target, sum - curSum - nums[i], i + , cnt + )) {
return true;
}
}
return false;
}
};
基于上面递归的优化方法的启发,博主将两个优化方法加到了之前写的迭代的暴力破解解法上,就能通过OJ了,perfect!
解法三:
class Solution {
public:
bool splitArray(vector<int>& nums) {
int n = nums.size();
vector<int> sums = nums;
for (int i = ; i < n; ++i) {
sums[i] = sums[i - ] + nums[i];
}
for (int i = ; i <= n - ; ++i) {
if (i != && nums[i] == && nums[i - ] == ) continue;
for (int j = i + ; j <= n - ; ++j) {
if (sums[i - ] != (sums[j - ] - sums[i])) continue;
for (int k = j + ; k <= n - ; ++k) {
int sum3 = sums[k - ] - sums[j];
int sum4 = sums[n - ] - sums[k];
if (sum3 == sum4 && sum3 == sums[i - ]) {
return true;
}
}
}
}
return false;
}
};
参考资料:
https://leetcode.com/problems/split-array-with-equal-sum/
https://leetcode.com/problems/split-array-with-equal-sum/discuss/101484/java-solution-dfs
https://leetcode.com/problems/split-array-with-equal-sum/discuss/101481/simple-java-solution-on2
[LeetCode] 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 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 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 into Fibonacci Sequence 分割数组成斐波那契序列
Given a string S of digits, such as S = "123456579", we can split it into a Fibonacci-like ...
- 【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 ...
- 『随笔』.Net 底层 数组[] 的 基本设计探秘 512 子数组
static void Main(string[] args) { Console.ReadKey(); //初始化数组 不会立即开辟内存字节, 只有实际给数组赋值时 才会开辟内存 // //猜测数组 ...
- [LeetCode] Split Array Largest Sum 分割数组的最大值
Given an array which consists of non-negative integers and an integer m, you can split the array int ...
随机推荐
- netstat/ps用法
1.netstat 语法 命令1:netstat -antp | grep :80(查看80端口被哪个服务占用)or netstat -antpuel | grep ":22&qu ...
- 听翁恺老师mooc笔记(5)--指针与数组
如果我们通过函数的参数将一个数组传递到参数中去,那么在函数里接收到的是什么东西呢?我们知道如果传递一个普通变量,那么参数接收到的是值,如果传递一个指针变量,参数接收到的也是值,只不过这时的值是地址.那 ...
- Archlinux下i3wm与urxvt的配置
前段时间学习了GitHub的两位前辈:Airblader和wlh320.他们的相关教程在https://github.com/Airblader/i3和https://github.com/wlh32 ...
- EXT3文件系统误删除导致文件系统中的邮件丢失恢复方法
一.故障描述 由8块盘组成的RAID5, 上层是EXT3文件系统,由于误删除导致文件系统中的邮件丢失 二.镜像磁盘为防止数据恢复过程中由于误操作对原始磁盘造成二次破坏, 使用winhex软件为每块磁盘 ...
- 【bug清除】新Surface Pro使用OneNote出现毛刺现象的解决方案
在写字的时候,左手触摸Surface的金属外壳背面,大概两个手指指肚大小.问题亲测可以得到解决. 推测是设备使用时接地没有做好,导致电磁笔出现偏移.问题初步锁定在新笔的倾斜感应上. 参考资料: htt ...
- python多目录字符串查找匹配
1. 需求来自于实际工作: 需要处理一批服务器上运行的redis实例,每个redis实例可能有密码,也可能没有,有密码的,密码配置格式一定是: requirepass XXXXX # XXXX是密码 ...
- Linux命令及lamp搭建
单纯属于Linux的命令:1.强制卸载有依赖关系的软件包: rpm -e httpd-2.2.15-26.el6.x86_64 --nodeps(--nodeps表示无依赖)4.删除当前目录所有的文件 ...
- EasyUI datagrid 使用小结
用了 EasyUI 框架一段时间了,这个前端框架用起来还是挺方便的,也有很多现成的控件,看看官方文档应该还是能比较快用起来的. 在这里记录一下一些常用的控件的方法,遇到过的bug或者当初耗了一点时间来 ...
- mysql常用命令整理
#不压缩备份 mysqldump -u root -p userpassword databasename > /tmp/backupfile.sql #压缩备份 mysqldump -u ro ...
- linux系统命令学习系列-例行任务管理at命令
先来复习一下上节内容: 切换用户身份命令su 以root身份执行操作命令sudo 作业:给user1配置sudo权限,不用密码,可执行useradd命令 在/etc/sudoers文件中添加如下配置项 ...