很久没刷leetcode了,今天心血来潮打开看了下,果断刷了每日一题。嗯……Runtime和Memory还可以,宝刀未老嘛嘻嘻……
标题:1524. Number of Sub-arrays With Odd Sum
难度:Medium
题目:Given an array of integers arr
, return the number of subarrays with an odd sum.
Since the answer can be very large, return it modulo 10^9 + 7
.
举例:输入:arr = [1, 3, 5]。 输出:4
解释:All subarrays are [[1],[1,3],[1,3,5],[3],[3,5],[5]] All sub-arrays sum are [1,4,9,3,8,5]. Odd sums are [1,9,3,5] so the answer is 4.
解题思路:考虑到题目只需要知道和为奇数的子序列的个数,不需要用额外的内存开销来保存子序列。而且根据数据奇偶特性:奇数+奇数=偶数;偶数+奇数=奇数;奇数+偶数=奇数;偶数+偶数=偶数。可以用单指针方法直接遍历数组,遍历到当前位置时,记录以当前位置为结束的所有子序列中奇数和的个数和偶数和的个数。如果当前位置的数字为偶数,则奇数和个数与上一状态相等,偶数和个数加1;如果当前位置的数字为奇数,上一状态奇偶和个数相反,偶数和个数加1。举例说明:
例:arr = [1, 2, 3, 4, 5, 6, 7],初始状态奇数和子序列个数odd = 0, 偶数和子序列个数even = 0, 记录最终结果的变量finalOdd = 0;
- i = 0:以i=0结束的只有一个子序列 [1], 1为奇数,even不变, odd++。 even = 0, odd = 1. 最后结果finalOdd += odd = 1;
- i = 1: 以i=1位置结束的有两个子序列:[1, 2], [2]。2为偶数,odd不变, even+1。因此even = 1 ([2]), odd = 1([1, 2]), finalOdd += odd = 2;
- i = 2; 以i = 2位置结束的有三个子序列[1, 2, 3], [2, 3], [3]。3为奇数,则上一状态的子序列([1, 2], [2]) 分别加3之后奇数和变偶数([1, 2] = 3 => [1, 2, 3] = 6), 偶数和变奇数([2] =2 => [2, 3] = 5),因此先交换odd和even的值:swap(odd, even); 因为多了[3], 因此odd需要再加1:odd += 1。odd = 2, even = 1. finalOdd += odd = 4;
- i = 3: 与步骤2类似,odd = 2, even = 2, finalOdd = 4+2=6;
- i = 4: 与步骤3类似,odd = 3, even = 2, finalOdd = 6 + 3 = 9;
- i = 5: 与步骤2类似,odd = 3, even = 3, finalOdd = 9 +3 = 12;
- i = 6: 与步骤3类似,odd = 4, even = 3, finalOdd = 12 + 4 = 16.
因此,最后结果为16. 因为题目中说数量可能很大,需要返回mod 1e9+7.因此需要在加之前判断一下
代码C++:
class Solution {
public:int numOfSubarrays(vector<int>& arr) {int odd = 0, even = 0, maxMod = 1e9 + 7;int finalOdd = 0;for(int i = 0; i < arr.size(); i++) {if (arr[i] % 2 == 0) {even ++;} else {swap(odd, even);odd++;}finalOdd = (finalOdd >= maxMod - odd) ? (finalOdd - maxMod + odd) : (finalOdd + odd);}return finalOdd;}
};
结果: