如何用O(n)实现四等分数组
来源:互联网 发布:mac 怎么使用语音朗读 编辑:程序博客网 时间:2024/05/21 10:20
第一次写博客还有点小紧张。前几天在一个比赛群里看到一道很有意思的算法题,题目如下:
给定一个数组,要求在数组里扣掉3个数后,所得到的4部分字数组的和相等,要求时间复杂度O(n)
题目本身并不难,难在要控制时间复杂度在O(n),一开始想了很多算法,时间复杂度还是控制不住,经过半天的思考,最终完成了代码(自己简单的测试了一下,思路应该是没问题,没找到OJ,测试数据也懒的想,有兴趣的朋友可以自行测试)。首先声明几点:
1.题目没有说数字的正负,现在好多算法题不够严谨,后来得知全部为正整数,思路一下就有了,但时候后来倒回来想,负数的情况应该也可以满足。
2.不知道有多少人会看到这篇文章,如果有什么问题,欢迎讨论,接受各种意见(大神无情的嘲讽都可以),重在交流。
回到正题,算法大致的思路是,首先计算出所有数字的和total,通过total可以算出每部分和的可能性,比如total为39,等分为4部分,则每一部分的和可能为1~9(保证在扣掉3个数字以后的total可以被4整除),大致划分出范围,便于之后的计算。
分别从数组的左右两边开始推进,维护left和right指针,同时对俩边各自的和进行累加,当两边和出现相等的情况时,我们认为此时存在有解的可能,需要进行下一步的判断。一开始在这里想了很多办法,一旦使用循环,复杂度必定大于O(n)。
关键的一部在于利用HashMap把本来的线性复杂度降为O(1)。下面贴一部分代码捎带讲解:
//key为当前节点距0的距离,value为当前节点的序号 HashMap<Integer, Integer> axis = new HashMap<>(); int total = 0; for(int i = 0;i < len; ++i) { total += data[i]; axis.put(total, i + 1); }
我们可以把整个数组抽象成一条延X方向的数轴,每个节点data[i]在数轴上对应的x坐标为data[0]~data[i]累加的和,把坐标作
为HashMap的key,对应的value是数组下标+1(稍后会看到value的作用)。
继续上面的思路,当然左右累加和相等时,我们需要进一步的计算得出是否满足四等分条件,这时通过计算可以得出第二和
第三部分对应的坐标(没错,就是HashMap),我们通过get()的返回值可以知道在假设有解的情况下,数组是否可以满足四等分。等
等,还差一步,即使我们通过计算得出,第二和第三部分可以被划分出来,我们只能扣掉3个值,二三中间是否有且仅有一个数字,
value发挥的作用时刻到了,value是每个节点的序号,可以直接判断得出结果。
以上就是所有的解题思路,蛮有意思的一道题(据说是阿里面试的时候给出的),比较符合校招的风格,题目不难,比较考验技
巧和平时对算法的练习程度,博主今年大三,很快面临实习,希望可以有个满意的结果,一起加油。最后贴上全部代码:
import java.util.HashMap;/** * Created by Administrator on 2017/3/3. */public class Divide { public static void main(String[] args) {// int[] data = {1, 8, 5, 2, 7, 9, 3, 6, 12, 2, 2, 5};// int[] data = {1, 8, 5, 2, 1, 3, 3, 2, 12, 2, 2, 5}; int[] data = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; System.out.println(divide(data)); } public static boolean divide(int[] data) { int len = data.length; //key为当前节点距0的距离,value为当前节点的序号 HashMap<Integer, Integer> axis = new HashMap<>(); int total = 0; for(int i = 0;i < len; ++i) { total += data[i]; axis.put(total, i + 1); } int max = 0; for(int i = total;i > 0; --i) { if(i % 4 == 0) { max = i / 4; break; } } System.out.println(total + " " + max); int left = 1; //左边开始累加 int addL = data[0]; int right = len - 2; //右边开始累加 int addR = data[len - 1]; while(left < right) { System.out.println(addL + " " + addR); if(addL == addR && addL <= max) { int low = 2 * addL + data[left]; int high = total - (2 * addR + data[right]); System.err.println(low + " " + high); if(axis.get(low) != null && axis.get(high) != null && axis.get(low) + 1 == axis.get(high)) { return true; } } if(addL < addR) { addL += data[left]; ++left; }else { addR += data[right]; --right; } } return false; }}
晚安。
- 如何用O(n)实现四等分数组
- 阿里-----数组四等分
- 数组四等分
- 趣题:如何用尺规作图将圆面积N等分
- unity实现N等分圆
- 问题:如何用递归实现数组求和?
- 如何用递归实现数组求和
- 如何用递归实现数组求和
- 如何用几何画板把圆奇数等分
- 阿里17实习生编程-数组四等分
- poj 1480 如何用程序实现m^n
- 【C语言】如何用递归的方法实现n^k
- 如何用O(n)时间复杂度查找第k大数的优化算法 C++程序
- java如何用数组解决大数阶乘的问题,例如求n!,n=100000
- 阿里在线编程,去除三个元素,四等分数组问题!
- 阿里实习在线编程测试--数组四等分
- 如何用开发N层软件-起步
- 如何用链表实现A U B,和 A n B呢?
- atoi函数源代码
- pureftp默认支持匿名用户的
- 关于js原型链 原型的个人理解
- ROS service入门到应用
- 玲珑杯round11-B:萌萌哒的第二题
- 如何用O(n)实现四等分数组
- JS中的prototype
- c++第一次试验作业
- 我的学习笔记之java环境配置
- 在绝望中寻找希望-中篇 写给年轻人
- Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
- MediaSession框架介绍
- 自定义View之简单自定义圆形进度条
- Mac 安装virtualbox 虚拟机用移动硬盘遇到的VERR_WRITE_PROTECT