描述
给定一个无序数组arr, 其中元素可正、可负、可0。给定一个整数k,求arr所有子数组中累加和为k的最长子数组长度
输入描述:
第一行两个整数N, k。N表示数组长度,k的定义已在题目描述中给出
第二行N个整数表示数组内的数
第二行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); } }