【三次过】Lintcode 139. 最接近零的子数组和

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

样例

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

挑战

O(nlogn)的时间复杂度


解题思路:

这道题求的是和最接近于0的子序列,暴力做法应该是N*N的时间复杂度,但是不能AC,所以在这里需要观察,所有子序列和的集合 = {0~n的子序列和,0~n的子序列和 - 0~m的子序列和},这里m<n。
所以由此我们可以知道,当(0n的子序列和)与(0m的子序列和)值非常接近的时候,则(m+1~n)即为所要求的最接近0的子序列。

当我们求到所有从0开始的子序列和,对其进行排序再遍历,我们可以得到每两个最接近的从0开始的子序列和。

最后,为了可以返回index,这里可以使用一个数据结构来一起保存sum和index。
利用sum排序,利用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
     */
    public int[] subarraySumClosest(int[] nums) {
        // write your code here
        int[] res = new int[2];
        if(nums == null || nums.length == 0)
            return res;
        if(nums.length == 1){
            res[0] = 0;
            res[0] = 0;
            return res;
        }
        
        //存储前i个数(包含i)的和与i下标
        Pair[] sums = new Pair[nums.length];

        for(int i=0, temp=0; i<nums.length; i++){
            temp += nums[i];
            sums[i] = new Pair(temp, i);
        }
        
        Arrays.sort(sums, new Comparator<Pair>(){
            @Override
            public int compare(Pair a, Pair b){
                return a.sum - b.sum;
            }
        });
        
        int closest = Integer.MAX_VALUE;
        for(int i=0; i<nums.length-1; i++){
            if(sums[i+1].sum - sums[i].sum < closest){
                closest = sums[i+1].sum - sums[i].sum;
                //left = left + 1, right = right
                res[0] = sums[i].index < sums[i+1].index ? sums[i].index + 1 : sums[i+1].index + 1;
                res[1] = sums[i].index >= sums[i+1].index ? sums[i].index : sums[i+1].index;
            }
        }
        
        return res;
    }
    
    class Pair{
        public int sum;
        public int index;
        public Pair(int sum, int index){
            this.sum = sum;
            this.index = index;
        }
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值