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

描述

给定一个无序数组arr, 其中元素可正、可负、可0。给定一个整数k,求arr所有子数组中累加和为k的最长子数组长度

输入描述:

第一行两个整数N, k。N表示数组长度,k的定义已在题目描述中给出
第二行N个整数表示数组内的数

输出描述:

输出一个整数表示答案

示例1

输入:
5 0
1 -2 1 1 1

输出:
3

思路

动态规划求解,用一个哈希表记录前缀和及其出现时的元素位置,当遇到一个没见过的前缀和presum时,就将其加入到哈希表中。如果哈希表中存在presum-k,说明从上一次presum出现的下一个位置到当前位置,数组元素的累加和为k,可以更新最长长度。这里可以看到presum出现的位置在更新最长长度时是需要用的,因此为了保证数组长度尽可能长,对于某个前缀和而言,哈希表中只存储它第一次出现的位置。

import java.util.Scanner;
import java.util.HashMap;

public class Main{
    
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        
        int n = scanner.nextInt();
        int k = scanner.nextInt();
        int[] arr = new int[n];
        
        for(int i=0;i<arr.length;i++){
            arr[i]=scanner.nextInt();
        }
        //map中的key用来记录累加和,对应的value是这个累加和第一次出现的下标
        HashMap<Integer,Integer> map = new HashMap<>();
        //这个很关键的,当数组从0开始的累加和是k时就会用到,所以一定要保证<0,-1>已经在map中了,这个当前i个和等于k时就用到了
        map.put(0,-1);
        //sum用来记录数组前i项的和,length用来记录最后的答案
        int sum = 0;
        int length = 0;
        for(int i=0;i<arr.length;i++){
            sum += arr[i];
            //看看map中是否已经存过sum-k这个累加和了,有的话从那个值到目前的i就是length了
            if(map.containsKey(sum-k)){
                int j = map.get(sum-k);
                length = i-j>length?i-j:length;
            }
            if(!map.containsKey(sum)){
                map.put(sum,i);
            }
        }
      System.out.println(length);
    }
}

 

posted @ 2022-01-11 14:07  思凡念真  阅读(36)  评论(0编辑  收藏  举报