Given an nonnegative integer array, find a subarray where the sum of numbers is k.
Your code should return the index of the first number and the index of the last number.Example
Given [1, 4, 20, 3, 10, 5], sum k = 33, return [2, 4].

题解1 - 哈希表

题 Zero Sum Subarray | Data Structure and Algorithm 的升级版,这道题求子串和为 K 的索引。首先我们可以考虑使用时间复杂度相对较低的哈希表解决。前一道题的核心约束条件为 f(i1)−f(i2)=0,这道题则变为 f(i1)−f(i2)=k

C++:

#include <iostream>
#include <vector>
#include <map>using namespace std;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> subarraySum(vector<int> nums, int k){vector<int> result;// curr_sum for the first item, index for the second item// unordered_map<int, int> hash;map<int, int> hash;hash[0] = 0;int curr_sum = 0;for (int i = 0; i != nums.size(); ++i) {curr_sum += nums[i];if (hash.find(curr_sum - k) != hash.end()) {result.push_back(hash[curr_sum - k]);result.push_back(i);return result;} else {hash[curr_sum] = i + 1;}}return result;}
};int main(int argc, char *argv[])
{int int_array1[] = {1, 4, 20, 3, 10, 5};int int_array2[] = {1, 4, 0, 0, 3, 10, 5};vector<int> vec_array1;vector<int> vec_array2;for (int i = 0; i != sizeof(int_array1) / sizeof(int); ++i) {vec_array1.push_back(int_array1[i]);}for (int i = 0; i != sizeof(int_array2) / sizeof(int); ++i) {vec_array2.push_back(int_array2[i]);}Solution solution;vector<int> result1 = solution.subarraySum(vec_array1, 33);vector<int> result2 = solution.subarraySum(vec_array2, 7);cout << "result1 = [" << result1[0] << " ," << result1[1] << "]" << endl;cout << "result2 = [" << result2[0] << " ," << result2[1] << "]" << endl;return 0;
}

输出:

result1 = [2 ,4]
result2 = [1 ,4]

源码分析

与 Zero Sum Subarray 题的变化之处有两个地方,第一个是判断是否存在哈希表中时需要使用hash.find(curr_sum - k), 最终返回结果使用result.push_back(hash[curr_sum - k]);而不是result.push_back(hash[curr_sum]);

复杂度分析

略,见 Zero Sum Subarray | Data Structure and Algorithm

题解2 - 利用单调函数特性

不知道细心的你是否发现这道题的隐含条件——nonnegative integer array, 这也就意味着子串和函数 f(i) 为「单调不减」函数。单调函数在数学中可是重点研究的对象,那么如何将这种单调性引入本题中呢?不妨设 i2>i1, 题中的解等价于寻找 f(i2)−f(i1)=k, 则必有 f(i2)≥k.

我们首先来举个实际例子帮助分析,以整数数组 {1, 4, 20, 3, 10, 5} 为例,要求子串和为33的索引值。首先我们可以构建如下表所示的子串和 f(i).

f(i) 1 5 25 28 38
i 0 1 2 3 4

要使部分子串和为33,则要求的第二个索引值必大于等于4,如果索引值再继续往后遍历,则所得的子串和必大于等于38,进而可以推断出索引0一定不是解。那现在怎么办咧?当然是把它扔掉啊!第一个索引值往后递推,直至小于33时又往后递推第二个索引值,于是乎这种技巧又可以认为是「两根指针」。

C++:

#include <iostream>
#include <vector>
#include <map>using namespace std;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> subarraySum2(vector<int> &nums, int k){vector<int> result;int left_index = 0, curr_sum = 0;for (int i = 0; i != nums.size(); ++i) {while (curr_sum > k) {curr_sum -= nums[left_index];++left_index;}if (curr_sum == k) {result.push_back(left_index);result.push_back(i - 1);return result;}curr_sum += nums[i];}return result;}
};int main(int argc, char *argv[])
{int int_array1[] = {1, 4, 20, 3, 10, 5};int int_array2[] = {1, 4, 0, 0, 3, 10, 5};vector<int> vec_array1;vector<int> vec_array2;for (int i = 0; i != sizeof(int_array1) / sizeof(int); ++i) {vec_array1.push_back(int_array1[i]);}for (int i = 0; i != sizeof(int_array2) / sizeof(int); ++i) {vec_array2.push_back(int_array2[i]);}Solution solution;vector<int> result1 = solution.subarraySum2(vec_array1, 33);vector<int> result2 = solution.subarraySum2(vec_array2, 7);cout << "result1 = [" << result1[0] << " ," << result1[1] << "]" << endl;cout << "result2 = [" << result2[0] << " ," << result2[1] << "]" << endl;return 0;
}

输出:

result1 = [2 ,4]
result2 = [1 ,4]

源码分析

使用for循环, 在curr_sum > k时使用while递减curr_sum, 同时递增左边索引left_index, 最后累加curr_sum。如果顺序不对就会出现 bug, 原因在于判断子串和是否满足条件时在递增之后(谢谢 @glbrtchen 汇报 bug)。

复杂度分析

看似有两重循环,由于仅遍历一次数组,且索引最多挪动和数组等长的次数。故最终时间复杂度近似为 O(2n), 空间复杂度为 O(1).

转载于:https://www.cnblogs.com/lyc94620/p/10119735.html

Subarray Sum K相关推荐

  1. LeetCode Subarray Sum Equals K

    原题链接在这里:https://leetcode.com/problems/subarray-sum-equals-k/description/ 题目: Given an array of integ ...

  2. LeetCode 325. Maximum Size Subarray Sum Equals k

    这一题开始以为是sliding window,后来发现,因为有负数,sum不具有单调性,没有办法用slidng window找出optimal solution. 如果考虑brute force的做法 ...

  3. LintCode 402: Continuous Subarray Sum

    LintCode 402: Continuous Subarray Sum 题目描述 给定一个整数数组,请找出一个连续子数组,使得该子数组的和最大.输出答案时,请分别返回第一个数字和最后一个数字的下标 ...

  4. [LintCode] Minimum Size Subarray Sum 最小子数组和的大小

    Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...

  5. Leetcode 560. Subarray Sum Equals K

    前缀和(prefix sum/cumulative sum) import collectionsclass Solution(object):def subarraySum(self, nums, ...

  6. LeetCode 523. Continuous Subarray Sum

    题目: Given a list of non-negative numbers and a target integer k, write a function to check if the ar ...

  7. LeetCode-Easy部分中标签为Dynamic Programming 523. Continuous Subarray Sum

    原题 Given a list of non-negative numbers and a target integer k, write a function to check if the arr ...

  8. [JAVA]寻找满足和的最短子序列(Minimum Size Subarray Sum)

    题目来源:leetcode 题目描述: Given an array of n positive integers and a positive integer s, find the minimal ...

  9. 523. Continuous Subarray Sum

    class Solution { public:bool checkSubarraySum(vector<int>& nums, int k) {unordered_map< ...

  10. leetcode523 Continuous Subarray Sum

    思路: 令sum[p]表示p位置的前缀和.如果sum[i] % k == sum[j] % k (j - i > 1),则存在子段(i, j]的和能够整除k. 实现: 1 class Solut ...

最新文章

  1. linux下文件夹函数,如何从linux上的文件夹中找到一个函数
  2. activiti监听器使用
  3. 什么是区块链钱包?区块链钱包如何运作?
  4. 跟着别人的感觉做网络推广之二
  5. OpenJudge计算概论-最长单词2
  6. 2018全球大学AI排名发布,中国高校表现强势!
  7. 8. OD-输入错误的信息注册未注册的软件
  8. docker和数据卷问题探究
  9. 智能指针(一):STL auto_ptr实现原理
  10. f-stack nginx 多进程模式启动 main_loop 流程分析
  11. Centos7 设置环境变量
  12. 【.Net MF网络开发板研究-06】以太网转串口
  13. 服务器安装esxi系统
  14. Blender3.0资产浏览器
  15. Unity3D新手入门教程_游戏开发100集课程 (含粒子
  16. 阿里云服务器怎么重置密码?服务器登录密码忘记了怎么办?
  17. 【原创】微信双开是定时炸弹?关于非越狱iOS上微信分身高危插件ImgNaix的分析
  18. 大屏可视化低代码开发平台网址
  19. 中船嘉年华邮轮揭幕全新企业品牌标识;美国运通全球商务旅行完成对Expedia集团旗下易信达的收购 | 全球旅报...
  20. 月薪3500的我,是怎样把自己 “逼”成月入十万的?

热门文章

  1. k-近邻算法 ---sklearn
  2. AttributeError: ‘Polygon‘ object has no property ‘normed‘
  3. 安装opcenccv-python以后仍然No module named ‘cv2‘
  4. conda: command not found
  5. 【Caffe代码解析】Layer网络层
  6. python日期模块datetime常用操作总结(字符串与datetime对象互转、日期差值计算、时间戳获取、时间数组生成等)
  7. 基于网页分析构思出的正文提取算法
  8. 很特别的动态规划教程
  9. java和python互相调用
  10. 机器学习(二)——贝叶斯算法