LeetCode 327 Count of Range Sum

Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.
Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j (i ≤ j), inclusive.

Note:
A naive algorithm of O(n2) is trivial. You MUST do better than that.

Example:
Given nums = [-2, 5, -1]lower = -2upper = 2,
Return 3.
The three ranges are : [0, 0][2, 2][0, 2] and their respective sums are: -2, -1, 2.


题意: 给一个数组,如果该数组的一个子数组,元素之和大于等于给定的一个参数值(lower),小于等于一个给定的参数值(upper),那么这为一组解,求总共有几组解。

方法一 Time Limit Exceeded ,直接暴力求解,时间复杂度为O(n^2),并且也不符合题意

	public int countRangeSum2(int[] nums, int lower, int upper) {
		long[] sum = new long[nums.length + 1];
		if (nums.length == 0) return 0;
		int res = 0;
		for (int i = 0; i < nums.length; i++) {
			sum[i + 1] = nums[i] + sum[i];
		}
		for (int i = 0; i < sum.length; i++) {
			for (int j = i + 1; j <= sum.length; j++) {
				long tmp = sum[j] - sum[i];
				if (tmp <= upper && tmp >= lower) res++;
			}
		}
		return res;
	}

方法二:看了半天才明白, 这里我们的排序对象是前缀求和数组sum,我们有左数组a和右数组b,且a和b数组都是排好序的,在归并排序的合并a,b之前,我们可以用i遍历左数组a,j,k两个指针分别取在右数组b搜索,使得:

  • sums[k] - sums[i] < lower
  • sums[j] - sums[i] <= upper

那么此时,我们就找到了j-k个符合要求的子数组个数。

数组a,b在归并之前,sum的相对顺序没有改变,而且a和b也未曾见过面,是没有相减过的,所以拿b-a是非常合理的。

所以用到归并排序降低了算法复杂度,归并排序的复杂度是n*logn。

	public int countRangeSum(int[] nums, int lower, int upper) {
		int n = nums.length;
		long[] sums = new long[n + 1];
		for (int i = 0; i < n; ++i) sums[i + 1] = sums[i] + nums[i];
		return countWhileMergeSort(sums, 0, n + 1, lower, upper);
	}

	private int countWhileMergeSort(long[] sums, int start, int end, int lower, int upper) {
		if (end - start <= 1) return 0;
		int mid = (start + end) / 2;
		int count = countWhileMergeSort(sums, start, mid, lower, upper)
				+ countWhileMergeSort(sums, mid, end, lower, upper);
		int j = mid, k = mid, t = mid;
		long[] cache = new long[end - start];
		for (int i = start, r = 0; i < mid; ++i, ++r) {
			while (k < end && sums[k] - sums[i] < lower) k++;
			while (j < end && sums[j] - sums[i] <= upper) j++;
			while (t < end && sums[t] < sums[i]) cache[r++] = sums[t++];
			cache[r] = sums[i];
			count += j - k;
		}
		System.arraycopy(cache, 0, sums, start, t - start);
		return count;
	}

https://discuss.leetcode.com/topic/33738/share-my-solution


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值