最近一郑州轻工业大学的学生找了一份实习的工作,HR给出了高达一千的月薪,并且在实习生考核优秀的情况下才会有,不优秀的情况下一毛钱都没有,只报销回去的路费。郑州轻工业大学虽然不是什么名校,但C++开发一个月最高才能拿到1000块钱的薪资,这也太侮辱人了。看这HR聊天的态度估计最多也只能拿个路费,并且还要干满一个月,如果不到一个月,连路费都没有,即便是在十多年前也没见过这么无耻的公司,还去干啥啊。
--------------下面是今天的算法题--------------
来看下今天的算法题,这题是LeetCode的第525题:连续数组。
问题描述
难度:中等
给定一个二进制数组nums,找到含有相同数量的0和1的最长连续子数组,并返回该子数组的长度。
示例1:
输入:nums=[0,1]输出:2说明:[0,1]是具有相同数量0和1的最长连续子数组。
示例2:
输入:nums=[0,1,0]输出:2说明:[0,1](或[1,0])是具有相同数量0和1的最长连续子数组。
问题分析
这题实际上是让求一个最长的子数组,并且这个子数组中0和1的数量必须相同。因为数组中的元素只能是0或1,直接计算不太好解,我们可以换种思路,把数组中的0换成-1。
这样0和1的数量必须相同就变成了-1和1的数量必须相同了,它们相加的结果肯定是0,所以这题就变成了求一个最长的子数组,并且这个子数组的和必须是0。
我们以示例2为例来看下,改变之后的数组就变成了[-1,1,-1]。那么这题的解题思路就很明确了,我们可以直接使用前缀和,对改变之后的数组进行累加,然后使用一个map对累加的值进行存储,因为是求最大长度,如果遇到相同的值则不能覆盖。
关于前缀和的知识以及求最大长度,最小长度还有求频率的总结,大家可以参考我书中的10.3.3节,这里就不在过多介绍。
累加的时候如果出现相同的值,只需要用当前值的下标减去前面相同值的下标,中间这段就是和为0的子数组,我们只需要保存它的长度,记录最大值即可。
这里还要注意使用map存储前缀和的时候,要考虑0的情况,也就是说如果从数组的第一个元素到当前元素nums[i]的和是0,那么这个长度就是i+1,因为数组的下标是从0开始的,所以这里前缀和为0的时候,我们给它一个默认值-1。
JAVA:
publicintfindMaxLength(int[]nums){Mapmap=newHashMap<>();map.put(0,-1);//前缀和为0的时候,给一个默认值-1。intpreSum=0,max=0;for(inti=0;i C++: public:intfindMaxLength(vector&nums){unordered_mapmp;mp[0]=-1;//前缀和为0的时候,给一个默认值-1。intpreSum=0,maxLength=0;for(inti=0;i