Subarray子数组

该题型多采用prefixSum的方法:

(一)Maximum Subarray (Frequent ++)

https://leetcode.com/problems/maximum-subarray/description/

题目:找到数组中总和最大的子集并返回该子集总和;

解答:从头到尾依次遍历数组,实时记录最大的sum值和最小的sum值。每次只需比较当前最大值和当前sum-最小sum的值,即可更新最大sum值。

改进:可以把求prefixSum的循环和找最大的循环合并成一个

代码:

class Solution {
    public int maxSubArray(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        
        int max = Integer.MIN_VALUE;
        int sum = 0;
        int minSum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
            max = (sum - minSum) > max ? (sum - minSum) : max;
            minSum = sum < minSum ? sum : minSum;
        }
        return max;
    }
}


(二)Subarray Sum Equals K

https://leetcode.com/problems/subarray-sum-equals-k/description/

题目:找到和为K的子集并返回满足该条件子集的个数;

解答:先将元素组变成累加和的数组,再依次遍历并比较;

代码:
class Solution {
    public int subarraySum(int[] nums, int k) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        
        int res = 0;
        
        for (int i = 1; i < nums.length; i++) {
            nums[i] += nums[i - 1];
        }
        for (int i = 0; i < nums.length; i++) {
             if (nums[i] == k) {
                 res++;
             }
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[j] - nums[i] == k) {
                   res++;
                }
            }
        }
        return res;
    }
}

(三)Subarray Sum closest 

http://www.lintcode.com/en/problem/subarray-sum-closest/

题目:找出数组中子集和最接近0的首、尾index;

解答:将序列index和对应的prefixSum存在map中,将prefixSum单独存在一个序列里,将该序列排序,依次比较相邻元素将差值较小的元素序列号提取出来,比较大小,依次更新res[0]和res[1]。

第一次犯错:时间复杂度太高,超时;

第二次犯错:使用map,prefixSum相同的元素会覆盖,导致结果错误;
解答:当prefixSum存在相同元素时,说明存在子数列和为0,故无需覆盖,直接返回首位值即可;

第三次犯错:单独把最后一个元素加入map时,忘记判断该元素是否已存在于序列中(循坏未覆盖,需单独判断)

代码:
public class Solution {
    /**
     * @param nums: A list of integers
     * @return: A list of integers includes the index of the first number 
     *          and the index of the last number
     */
    public int[] subarraySumClosest(int[] nums) {
        // write your code here
        int[] res = new int[2];
        int[] prefixSum = new int[nums.length + 1];
        int diff = Integer.MAX_VALUE;
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int i = 0; i < nums.length; i++) {
           prefixSum[i + 1] = prefixSum[i] + nums[i];
           if (!map.containsKey(prefixSum[i])) {
               map.put(prefixSum[i], i);
            } else {
                res[0] = map.get(prefixSum[i]);
                res[1] = i - 1;
                return res;
            }
        }
        
        if (!map.containsKey(prefixSum[nums.length])) {
            map.put(prefixSum[nums.length], nums.length);
        } else {
            res[0] = map.get(prefixSum[nums.length]);
            res[1] = nums.length - 1;
            return res;
        }
        
        Arrays.sort(prefixSum);
        for (int i = 1; i < nums.length + 1; i++) {
            if (prefixSum[i] - prefixSum[i - 1] < diff) {
                int i1 = map.get(prefixSum[i]);
                int i2 = map.get(prefixSum[i - 1]);
                diff = prefixSum[i] - prefixSum[i - 1];
                res[0] = Math.min(i1, i2);
                res[1] = Math.max(i1, i2) - 1;
            }
        }
        return res;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值