描述
给定一个整数数组,找到一个和最接近于零的子数组。返回第一个和最右一个指数。你的代码应该返回满足要求的子数组的起始位置和结束位置
您在真实的面试中是否遇到过这个题? 是
样例
给出[-3, 1, 1, -3, 5]
,返回[0, 2]
,[1, 3]
, [1, 1]
, [2, 2]
或者 [0, 4]
。
挑战
O(nlogn)的时间复杂度
分析:
此题是子数组和为零的变形题,由于要求的子串和不一定,故哈希表的方法不再适用,使用解法4 - 排序即可在 O(nlogn) 内解决。具体步骤如下:
- 首先遍历一次数组求得子串和。
- 对子串和排序。
- 逐个比较相邻两项差值的绝对值,返回差值绝对值最小的两项。
代码:
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) {
// write your code here
vector<int>result;
if(nums.empty())
return result;
const int num_size=nums.size();
vector<pair<int,int>>sum_index(num_size+1);
for(int i=0;i<num_size;i++)
{
sum_index[i+1].first=sum_index[i].first+nums[i];
sum_index[i+1].second=i+1;
}
sort(sum_index.begin(),sum_index.end());
int min_diff=INT_MAX;
int closest_index=1;
for(int i=1;i<num_size+1;i++)
{
if(abs(sum_index[i].first-sum_index[i-1].first)<min_diff)
{
min_diff=abs(sum_index[i].first-sum_index[i-1].first);
closest_index=i;
}
}
int start=min(sum_index[closest_index].second,sum_index[closest_index-1].second);
int end=max(sum_index[closest_index].second,sum_index[closest_index-1].second)-1;
result.push_back(start);
result.push_back(end);
return result;
}
};
举例说明:
数组: -5,4,2,-3
sum_index<0,0>
sum_index<-5,1>
sum_index<-1,2>
sum_index<1,3>
sum_Index<-2,4>
排序后:-5,-2,-1,0,1
min_diff: -3,1, 1, 1
closest_index=2, 对应排序后的-1,在sum_index中-1对应下标2
colsest_index=1,对应排序后的-2,在 sum_index中-2对应下标4
所以 start=min(2,4)=2, end=max(2,4)-1=3。
此题只是让求解一个最接近零的子数组即可,所以题目中if语句使用的是<
如果需要求多个最接近零的子数组,那只能在得到最小值之后,在来一个for循环,if语句中用等于。