139.Subarray Sum Closest-最接近零的子数组和(中等题)

本文介绍了一种寻找整数数组中最接近零的子数组和的方法,通过构建Sum数据结构并利用排序技巧来实现O(nlogn)的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最接近零的子数组和

  1. 题目

    给定一个整数数组,找到一个和最接近于零的子数组。返回第一个和最有一个指数。你的代码应该返回满足要求的子数组的起始位置和结束位置

  2. 样例

    给出[-3, 1, 1, -3, 5],返回[0, 2],[1, 3], [1, 1], [2, 2] 或者 [0, 4]。

  3. 挑战

    O(nlogn)的时间复杂度

  4. 题解

    本题求数组中区间[i,j],使得该区间内所有元素之和最接近于0。则Sum[i,j]=Sum[0,j]-Sum[0,i-1]。为了优化时间复杂度,我们构建一个数据结构Sum保存Sum[0,j]和j的值。
    对数组进行遍历,将Sum[0,j]及j依次存入一个Sum数组,再对其按sum属性大小进行排序,此时只需找到一对Sum[a],Sum[b]使得Sum[a]-Sum[b]最小,则从a,b的index属性即可得到答案。
    如nums[-3, 1, 1, -3, 5],
    遍历后得到Sum数组[0(0),-3(1),-2(2),-1(3),-4(4),1(5)],括号中表示index属性。
    排序后得到[-4(4),-3(1),-2(2),-1(3),0(0),1(5)],
    遍历可知Sum[a]-Sum[b]最小值为1,取a=1(5),b=-4(4),再从index值分析可得到答案。

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
     */
    class Sum
    {
        public int sum;
        public int index;
        public Sum(int sum, int index)
        {
            this.sum = sum;
            this.index = index;
        }
    }

    public int[] subarraySumClosest(int[] nums) {
        int[] res = new int[2];
        if (nums == null || nums.length == 0) 
        {
            return res;
        } 

        int len = nums.length;
        if(len == 1) 
        {
            res[0] = res[1] = 0;
            return res;
        }
        Sum[] sums = new Sum[len+1];
        sums[0] = new Sum(0,0);
        int pre = 0;
        for (int i=1;i<=len;i++)
        {
            sums[i] = new Sum(pre + nums[i-1],i);
            pre = sums[i].sum;
        }
        Arrays.sort(sums, new Comparator<Sum>() 
        {
           public int compare(Sum a, Sum b) 
           {
               return a.sum - b.sum;
           } 
        });
        int min = Integer.MAX_VALUE;
        for (int i=1;i<=len;i++)
        {
            if (min > sums[i].sum - sums[i-1].sum)
            {
                min = sums[i].sum - sums[i-1].sum;
                res[0] = Math.min(sums[i].index, sums[i - 1].index);
                res[1] = Math.max(sums[i].index, sums[i - 1].index) - 1;
            }
        }
        return res;
    }
}

Last Update 2016.10.17

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值