leetcode: 连续子串和/积的相关题目汇总及总结

有一类题目,是给定一个数组,问里面是否有连续的子串,使得子串的和满足某种性质,比如是否为K,或者是否为K的倍数,或者子串的和最大,或者子串的乘积最大。

对于子串的和为某个数或某个数的倍数,一种很常见的做法是使用前缀和数组+map。

560. Subarray Sum Equals K

题目

Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.

Example 1:
Input:nums = [1,1,1], k = 2
Output: 2
Note:
The length of the array is in range [1, 20,000].
The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7].

给定一个数字,问里面有多少个连续的子数组,使得他们的和加起来为K.

解法一:使用前缀和数组,然后枚举所有的子数组,时间复杂度 O ( n 2 ) O(n^2) .
解法二:使用前缀和数组+map。map用于存储当前遇到的前缀和的次数,key为前缀和,value为到目前位置这个和出现的次数;在第i个位置遇到一个前缀和 s u m i sum_i ,看当前的前缀和与k之间的差 s u m i k sum_i -k 是否在map出现过。如果出现过,意味着在 i i 之前存在着某个 j < i j <i ,使得 s u m j = s u m i k sum_j=sum_i-k 。于是从 j j i i 的这个连续子串的和就是 s u m i s u m j = k sum_i -sum_j=k 。有几个这样的 j j 就有几个以 i i 结尾的满足条件的连续子串。
时间复杂度: O ( n l o g n ) O(nlogn) ,其中 l o g n logn 是访问map时的开销。

974. Subarray Sums Divisible by K

题目

Given an array A of integers, return the number of (contiguous, non-empty) subarrays that have a sum divisible by K.

Example 1:
Input: A = [4,5,0,-2,-3,1], K = 5
Output: 7
Explanation: There are 7 subarrays with a sum divisible by K = 5:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]

题目的意思是说,存在多少个连续的子串,每个子串的和都是K的倍数,0也是K的倍数,K不为0。这道题和上面的很相似的,只不过上面一题要求和为定值K,这道题要求和为K的倍数。
也可以使用上面那道题的思路来做,前缀和+map。

但是,现在如何消除的和为K的倍数的影响呢?使用模运算!!!,map只把 s u m % K sum \% K 当前key就可以啦,但是要保证 s u m % K sum \% K 是非负数,如果sum为负数,先让sum一直加K,直到非负为止。
这里是思路是这样的:对于当前位置 i i ,得到的前缀和 s u m i sum_i ,如果 s u m i % K sum_i \% K 在map中出现过。那么意味着存在某个 j < i j<i ,使得 s u m j % K sum_j\%K 等于 s u m i % K sum_i\%K ,这说明,从 i i j j 子串的和就是K的倍数。
时间复杂度: O ( n l o g n ) O(nlogn)

523. Continuous Subarray Sum

题目:

Given a list of non-negative numbers and a target integer k, write a function to check if the array has a continuous subarray of size at least 2 that sums up to a multiple of k, that is, sums up to n*k where n is also an integer.

Example 1:
Input: [23, 2, 4, 6, 7], k=6
Output: True
Explanation: Because [2, 4] is a continuous subarray of size 2 and sums up to 6.

这道题跟974是一个意思的,只不过多了一个条件:子串最少得有两个元素才行。
方法很简单,map的key为 s u m i % K sum_i\%K ,value为最早出现这个和的元素下标。
在遇到第i个元素的前缀和 s u m i % K sum_i\%K 的时候,看map里面有没有出现这个和,有的话看看这个出现过的和最小下标 j j 与当前位置 i i 的距离 i j i-j 是否超过1,如果超过,说明从 j j i i 有至少两个元素,而且他们的和是K的倍数。


求最大的连续子串和,连续子串积。当遇到最大、最小,这种取值不确定的问题时,就不能前缀和+map了。这个时候,一般考虑动态规划,寻找子问题,定义最优子结构。虽然,上面几道题的前缀和+map也是一种动态规划的算法。

53. Maximum Subarray

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Example:
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

这个就是很老的题目了。
给定一个数组,让求最大的连续子串和。

定义最优子问题为dp[i]:以第i个数字结尾的最大连续子串的和。
于是对于第i+1个元素来讲,以第i+1个元素结尾的最大连续子串和的子串,只能两个情况:第i+1个元素单独成串或第i+1个元素接在以第i个元素为结尾的最大连续子串和的子串后面。
于是dp[i+1]=max(dp[i]+num[i+1],num[i+1]).
代码

class Solution {
public:
	int maxSubArray(vector<int>& nums) {
		int rst = nums[0];
		vector<int>dp(nums.size(), 0);
		for (int i = 0; i < nums.size(); i++)
		{
			if (i == 0) {
				dp[i] = nums[i];
			}
			else
			{
				dp[i] = max(dp[i - 1] + nums[i], nums[i]);
				if (dp[i]>rst) rst = dp[i];
			}
		}
		return rst;
	}
};

121. Best Time to Buy and Sell Stock

题目

Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.
Note that you cannot sell a stock before you buy one.

Example 1:
Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Not 7-1 = 6, as selling price needs to be larger than buying price.
Example 2:
Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

没啥好多的,简单题

class Solution {
public:
	int maxProfit(vector<int>& prices) {
		if (prices.size() <= 1) return 0;
		int _min = prices[0];
		int rst = 0;
		for (int i = 0; i < prices.size(); i++)
		{
			if( (prices[i] - _min) > rst)
			{
				rst = prices[i] - _min;
			}
			if (prices[i]<_min)
			{
				_min = prices[i];
			}
		}
		return rst;
	}
};

713. Subarray Product Less Than K

题目:

Your are given an array of positive integers nums.
Count and print the number of (contiguous) subarrays where the product of all the elements in the subarray is less than k.

Example 1:
Input: nums = [10, 5, 2, 6], k = 100
Output: 8
Explanation: The 8 subarrays that have product less than 100 are: [10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6].
Note that [10, 5, 2] is not included as the product of 100 is not strictly less than k.
Note:
0 < nums.length <= 50000.
0 < nums[i] < 1000.
0 <= k < 10^6.

发布了307 篇原创文章 · 获赞 268 · 访问量 56万+

猜你喜欢

转载自blog.csdn.net/jmh1996/article/details/103448883