题解 | #未排序数组中累加和为给定值的最长子数组长度#

未排序数组中累加和为给定值的最长子数组长度

http://www.nowcoder.com/practice/704c8388a82e42e58b7f5751ec943a11

未排序数组中累加和为给定值的最长子数组长度

问题描述:给定一个无序数组arr, 其中元素可正、可负、可0。给定一个整数k,求arr所有子数组中累加和为k的最长子数组长度
示例
输入:[1,-2,1,1,1],0
返回值:3
说明:最长子数组为[1,-2,1],其长度为3

方法一

思路分析

本题我们能直接想到的办法就是暴力穷举,外层循环从数组开始位置遍历,内层循环遍历从上一层的位置开始,使用sum记录当前数组的和,如果达到k,将数组长度记录下来,之后继续向后遍历,当内层循环遍历到数组结束位置后,外层循环往下继续刚才的操作。这种方法时间复杂度较大。因此我们考虑使用前缀和数组,定义数组$pre[i]=arr[0]+arr[1]+...+arr[i-1]$,那么子数组$arr[i]$到$arr[j-1]$的和为$pre[j]-pre[i]$而后计算出所有可能的前缀和数组,特别的数组中第一个元素的前缀和初始化为0,接着我们根据子数组的可能的长度,按长度的最大值开始向下遍历,即按照数组长度由大到小找到原数组中可能的子数组,如果子数组的和$pre[j]-pre[i]$为k,则输出当前的子数组长度。

图解

输入:[1,-2,1,1,1],0
首先计算其前缀数组$pre[6]=\{0,1,-1,0,1,2\}$
$len$ 子数组的起止位置$i$ 子数组的和
5 0 $presum[0+5]-presum[0]=2$
4 0 $presum[0+4]-presum[0]=1$
1 $presum[1+4]-presum[1]=1$
3 0 $presum[0+3]-presum[0]=0$ $k=0$程序在此处运行结束
1
2

JAVA核心代码

import java.util.*;

public class Solution {
    /**
     * max length of the subarray sum = k
     * @param arr int整型一维数组 the array
     * @param k int整型 target
     * @return int整型
     */
    public int maxlenEqualK (int[] arr, int k) {
        int n=arr.length;
        int[] presum=new int[n+1];
        for(int i=0;i<n;i++){
            presum[i+1]=presum[i]+arr[i];////构建前缀和数组,开始元素的前缀和为0,因此设置n+1个长度
        }

        //逆序遍历所有可能的长度
        for(int len=n;len>=1;len--)
		{
            for(int i=0;i+len<=n;i++)
			{
                if(presum[i+len]-presum[i]==k)//长度为len的子数组的和
				{
                    return len;
                }
            }
        }
        return 0;
    }
}

复杂度分析

  • 时间复杂度:两层的循环,外层循环遍历$n$,内存循环遍历$n-len$,因此时间复杂度为$O(n^2)$
  • 空间复杂度: 借助于一个前缀数组,因此空间复杂度为$O(n)$


方法二

思路分析

本题也可采用哈希表的办法,将当前数组arr[0,i]的和做为关键字,i做为值记录在哈希表hashmap中,循环遍历数组,从开始位置出发,记录前缀数组的和presum,如果这个值不在哈希表中,则将其记录在哈希表中,继续判断presum-k是否在哈希表中,如果也在哈希表中,那么i-hashmap[presum-k]这一数值就可作为累加和为k的数组长度,但不一定是最长的,需要继续进行遍历,直到遍历完成。特别的由于数组中可能存在0,而子数组增加0,数组的和不变,长度会增加,因此初始hashmap[0]=-1,以避免以0开始的子数组的计算。

图解

输入:$[1,-2,1,1,1]$,$0$
初始化$hashmap[0]=-1$,$length$初始化为0
$i$ $presum +=arr[i]$ $hashmap$ $length$
$0$ $1$ $hashmap[1]=0$ $0$
$1$ $1+(-2)=-1$ $hashmap[-1]=1$ $0$
$2$ $-1+1=0$ ---------- $max(length,i-hashmap[presum-k])=max(0,3)=3$
$3$ $0+1=1$ ---------- $max(length,i-hashmap[presum-k])=max(3,3)=3$
$4$ $1+1=2$ $hashmap[2]=4$ $max(length,i-hashmap[presum-k])=max(3,0)=3$

python核心代码

#
# max length of the subarray sum = k
# @param arr int整型一维数组 the array
# @param k int整型 target
# @return int整型
#
class Solution:
    def maxlenEqualK(self , arr , k ):
        # write code here
        if arr == None&nbs***bsp;len(arr) == 0:
            return 0
        hashmap = {}#构建哈希表
        hashmap[0] = -1#防止数组中有0的情况,数组中增加0,数组的和不变,数组长度+1
        presum = 0
        length = 0
        for i in range(len(arr)):
            presum += arr[i]#构建前缀数组和
            if presum not in hashmap:#哈希表中为存放当前值
                hashmap[presum]=i
            if (presum - k) in hashmap:#presum-k的值在哈希表中,其长度也是最长的,因此可以直接计算总的长度
                length = max(length,i-hashmap[presum-k])

        return length

复杂度分析

  • 时间复杂度:遍历一次数组,因此时间复杂度为$O(n)$
  • 空间复杂度:   借助于一个presum变量以及一个哈希数组,因此空间复杂度为$O(n)$
全部评论

相关推荐

01-26 19:51
门头沟学院 Java
isabener:怎么感觉像群发的呢
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 长得好看会提高面试通过率吗? #
4018次浏览 46人参与
# 离家近房租贵VS离家远但房租低,怎么选 #
16907次浏览 137人参与
# MiniMax求职进展汇总 #
25164次浏览 322人参与
# 春招至今,你的战绩如何? #
15816次浏览 145人参与
# 你的实习产出是真实的还是包装的? #
3098次浏览 53人参与
# 沪漂/北漂你觉得哪个更苦? #
1553次浏览 41人参与
# 米连集团26产品管培生项目 #
7308次浏览 226人参与
# HR最不可信的一句话是__ #
1091次浏览 32人参与
# AI面会问哪些问题? #
946次浏览 23人参与
# 你做过最难的笔试是哪家公司 #
1247次浏览 22人参与
# AI时代,哪个岗位还有“活路” #
2853次浏览 51人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152905次浏览 889人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
8021次浏览 43人参与
# XX请雇我工作 #
51155次浏览 171人参与
# 简历第一个项目做什么 #
32148次浏览 361人参与
# 简历中的项目经历要怎么写? #
311051次浏览 4265人参与
# 投格力的你,拿到offer了吗? #
178339次浏览 891人参与
# 你最满意的offer薪资是哪家公司? #
76981次浏览 375人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
187605次浏览 1123人参与
# AI时代,哪些岗位最容易被淘汰 #
64760次浏览 890人参与
# 如果重来一次你还会读研吗 #
230018次浏览 2011人参与
# 正在春招的你,也参与了去年秋招吗? #
364353次浏览 2642人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务