算法之最长累计和篇(Java)

给定一个数组arr,和一个整数num,求在arr中,累加和等于num的最长 子数组的长度

例子: 

arr = {7,3,2,1,1,7,7,7}   

num = 7 其中有很多的子数组累加和等于7,但是最长的子数组是{3,2,1,1},所 以返回其长度4

	public static int zzzi_sumisit(int[] arr, int k) {
		if (arr == null || arr.length == 0) {
			return 0;
		}
		HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
		hashMap.put(0, -1);
		int len = 0;
		int sum = 0;
		for (int i = 0; i < arr.length; i++) {
			sum += arr[i];
			if (hashMap.containsKey(sum - k)) {
				len = Math.max(i - hashMap.get(sum - k), len);
			}
			if (!hashMap.containsKey(sum)) {
				hashMap.put(sum, i);
			}
		}
		return len;
	}

衍生(最长奇偶长度):

public class zzzi_sumisit2 {
	public static int zzzi_sumisit2(int[] arr, int k) {
		if (arr == null || arr.length == 0) {
			return 0;
		}
		HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
		hashMap.put(0, -1);
		int len = 0;
		int sum = 0;
		int[] bra = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			bra[i] = arr[i] % 2 == 1 ? 1 : -1;
			sum += bra[i];
			if (hashMap.containsKey(sum - k)) {
				len = Math.max(i - hashMap.get(sum - k), len);
			}
			if (!hashMap.containsKey(sum)) {
				hashMap.put(sum, i);
			}
		}
		return len;
	}

衍生:(最长1&2数量长度):

public class zzzi_sumisit3 {
	public static int zzzi_sumisit3(int[] arr, int k) {
		if (arr == null || arr.length == 0) {
			return 0;
		}
		HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
		hashMap.put(0, -1);
		int len = 0;
		int sum = 0;
		int[] help = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] == 2) {
				help[i] = -1;
			} else if (arr[i] == 1) {
				help[i] = 1;
			} else {
				help[i] = 0;
			}
			sum += help[i];
			if (hashMap.containsKey(sum - k)) {
				len = Math.max(i - hashMap.get(sum - k), len);
			}
			if (!hashMap.containsKey(sum)) {
				hashMap.put(sum, i);
			}
		}
		return len;
	}

衍生之最多异或和为0:

	public static int zzzi_sumisit4(int[] arr) {
		if (arr == null || arr.length == 0) {
			return 0;
		}
		HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
		hashMap.put(0, -1);
		int[] mosts = new int[arr.length];
		int max = 0;
		int cer = 0;
		for (int i = 0; i < arr.length; i++) {
			cer ^= arr[i];
			if (hashMap.containsKey(cer)) {
				int coco = hashMap.get(cer);
				mosts[i] = coco == -1 ? 1 : mosts[coco] + 1;
			}
			if (i > 0) {
				mosts[i] = Math.max(mosts[i - 1], mosts[i]);
			}
			hashMap.put(cer, i);
			max = Math.max(max, mosts[i]);
		}
		return max;
	}

实践题(摘自牛客网)

在o(n)下,求出给定数组中小于等于aim的最长的len长度:

运用的方法是:window方法,双指针,从后面开始往回推,形成一个块,可当作加速!!

	public static int sumisit5(int[] arr, int aim) {
		int[] index = new int[arr.length];
		int[] end = new int[arr.length];
		index[arr.length - 1] = arr[arr.length - 1];
		end[arr.length - 1] = arr.length - 1;
		for (int i = arr.length - 2; i >= 0; i--) {
			if (index[i + 1] < 0) {
				index[i] = index[i+1] + arr[i];
				end[i] = end[i+1];
			} else {
				index[i] = arr[i];
				end[i] = i;
			}
		}
		int len = 0;
		int sum = 0;
		int right = 0;
		for (int left = 0; left < arr.length; left++) {
			while (right < arr.length && sum + index[right] <= aim) {
				sum += index[right];
				right = end[right] + 1;
			}
			sum  -= right == left ?  0 : arr[left];
			len   = Math.max(len, right - left);
			right = Math.max(right, left + 1);
		}
		return len;		
	}
	

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值