0
点赞
收藏
分享

微信扫一扫

程序员代码面试指南第二版 125.未排序数组中累加和为给定值的最长子数组长度


​​welcome to my blog​​

程序员代码面试指南第二版 125.未排序数组中累加和为给定值的最长子数组长度

题目描述

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

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

输出描述:
输出一个整数表示答案

示例1

输入
5 0
1 -2 1 1 1

输出
3

第一次做; 核心:sum的含义:子数组arr[i,j]的累加和; a-b=k等价于a-k=b; 哈希表中只记录前缀和最早出现的索引; 为了记录arr[0,i]这个子数组的情况,需要先往哈希表中插入(0,-1)这个记录, 这样当sum=k时,也就是sum-k=0时,能够获取子数组arr[0,i]的长度

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

public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] str = sc.nextLine().split(" ");
int n = Integer.parseInt(str[0]);
int k = Integer.parseInt(str[1]);
str = sc.nextLine().split(" ");
int[] arr = new int[n];
for(int i=0; i<n; i++){
arr[i] = Integer.parseInt(str[i]);
}
//
//核心:A-B=k, 等价于A-k=B
//key表示arr[0,i]的累加和, value表示该累加和
//map中只存储一个累加和最早出现的位置, 这样才能获取最大的子数组长度
HashMap<Integer,Integer> map = new HashMap<>();
//如果sum=k, 也就是sum-k=0, 那么map中必须得有key=0的记录, 否则就没法记录子数组arr[0,i]对应的长度了
map.put(0, -1);
//sum表示子数组arr[0,i]的累加和
int sum = 0, len=0;
for(int i=0; i<n; i++){
sum = sum + arr[i];
if(map.containsKey(sum-k)){
len = Math.max(len, i-map.get(sum-k));
}
//当次循环中, 只用到了sum-k的哈希值, 没有用到sum的哈希值,所以可以把sum哈希值的操作放在最后
if(!map.containsKey(sum))
map.put(sum,i);
}
System.out.print(len);
}
}

125补充题1

题目描述

给定一个无序数组arr,其中元素可正、可负、可0。求arr所有子数组中正数与负数个数相等的最长子数组的长度。
[要求]
时间复杂度为O(n),空间复杂度为O(n)

输入描述:
第一行一个整数N,表示数组长度
接下来一行有N个数表示数组中的数

输出描述:
输出一个整数表示答案

示例1

输入
5
1 -2 1 1 1

输出
2

第一次做; 把正数看成1, 负数看成-1, 0不变, 还是求累加和, 正数个数和负数个数相等,也就是k=0; 个数相等问题转换成累加和,进而使用哈希表前缀和方法, 提前明确k的值

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

public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] str = sc.nextLine().split(" ");
int n = Integer.parseInt(str[0]);
//int k = Integer.parseInt(str[1]);
str = sc.nextLine().split(" ");
int[] arr = new int[n];
for(int i=0; i<n; i++){
arr[i] = Integer.parseInt(str[i]);
}
//
//核心:A-B=k, 等价于A-k=B
//key表示arr[0,i]的累加和, value表示该累加和
//map中只存储一个累加和最早出现的位置, 这样才能获取最大的子数组长度
HashMap<Integer,Integer> map = new HashMap<>();
//如果sum=k, 也就是sum-k=0, 那么map中必须得有key=0的记录, 否则就没法记录子数组arr[0,i]对应的长度了
map.put(0, -1);
//sum表示子数组arr[0,i]的累加和
int sum = 0, len=0;
for(int i=0; i<n; i++){
if(arr[i]>0)
sum = sum + 1;
else if(arr[i]<0)
sum = sum - 1;
//arr[i]==0时不需要更新sum

if(map.containsKey(sum)){
len = Math.max(len, i-map.get(sum));
}
//当次循环中, 只用到了sum-k的哈希值, 没有用到sum的哈希值,所以可以把sum哈希值的操作放在最后
if(!map.containsKey(sum))
map.put(sum,i);
}
System.out.print(len);
}
}

125补充题2

题目描述

给定一个无序数组arr,其中元素只能是1或0。求arr所有的子数组中0和1个数相等的最长子数组的长度 
[要求]
时间复杂度为O(n),空间复杂度为O(n)

输入描述:
第一行一个整数N,表示数组长度
接下来一行有N个数表示数组中的数

输出描述:
输出一个整数表示答案

示例1

输入
5
1 0 1 0 1

输出
4

第一次做; 核心:个数相等问题转换成累加和, 进而用哈希表前缀和解决

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

public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] str = sc.nextLine().split(" ");
int n = Integer.parseInt(str[0]);
//int k = Integer.parseInt(str[1]);
str = sc.nextLine().split(" ");
int[] arr = new int[n];
for(int i=0; i<n; i++){
arr[i] = Integer.parseInt(str[i]);
}
//
//核心:A-B=k, 等价于A-k=B
//key表示arr[0,i]的累加和, value表示该累加和
//map中只存储一个累加和最早出现的位置, 这样才能获取最大的子数组长度
HashMap<Integer,Integer> map = new HashMap<>();
//如果sum=k, 也就是sum-k=0, 那么map中必须得有key=0的记录, 否则就没法记录子数组arr[0,i]对应的长度了
map.put(0, -1);
//sum表示子数组arr[0,i]的累加和
int sum = 0, len=0;
for(int i=0; i<n; i++){
if(arr[i]==0)
sum = sum - 1;
else
sum = sum + 1;

if(map.containsKey(sum)){
len = Math.max(len, i-map.get(sum));
}
//核心: 当次循环中, 只用到了sum-k的哈希值, 没有用到sum的哈希值,所以可以把sum哈希值的操作放在最后
if(!map.containsKey(sum))
map.put(sum,i);
}
System.out.print(len);
}
}


举报

相关推荐

0 条评论