前缀和应用-最接近0的子数组和

lintcode 139

描述

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

输入:
[-3,1,1,-3,5]
输出:
[0,2]
解释: [0,2], [1,3], [1,1], [2,2], [0,4] 都可以

要求时间复杂度O(nlogn)

分析

暴力的想法是O(n^2)的方法来找出所有的组合,再判断是否接近0;
进阶一点的想法是利用前缀和,O(n)的过程可以求0,i的和sum[i],sum[j]-sum[i-1]就可以得到i-j之间的和,用dp也好其他方法也好,要求出所有的组合来,也是O(n^2);
进一步想。 O(nlogn)往往是二分或者排序,可以联想到排序。(我好恨我面试的时候为什么没想到这一点!!)
把所有的sum[i]及其下标一起排序,那么相邻的sum[i]就是接近的,只要找最接近的两个就行,两者的查所得的子数组和就是最接近0的。

代码

class Solution {
public:
    /*
     * @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
     */
    vector<int> subarraySumClosest(vector<int> &nums) {
        vector<int>ans;
        // write your code here
        vector<pair<int,int> >sum;
        int temp = 0;
        sum.push_back(make_pair(temp,-1));
        int len = nums.size();
        for(int i = 0;i<len;i++){
            temp += nums[i];
            sum.push_back(make_pair(temp,i));
        }
        sort(sum.begin(),sum.end()); //按和排序
        int diff = INT_MAX;
        int start=0,end=0; //只有一个数的时候就返回0,0
        for(int i = 1;i<len;i++){
            if(abs(sum[i].first - sum[i-1].first)<=diff){
                diff = abs(sum[i].first - sum[i-1].first);
                start = min(sum[i].second, sum[i-1].second)+1; //注意这里 是差一个的
                end = max(sum[i].second,sum[i-1].second);
            }
        }
        ans.push_back(start);
        ans.push_back(end);
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值