如果数组的每一对相邻元素都是两个奇偶性不同的数字,则该数组被认为是一个 特殊数组 。
周洋哥有一个整数数组 nums
和一个二维整数矩阵 queries
,对于 queries[i] = [fromi, toi]
,请你帮助周洋哥检查子数组 nums[fromi..toi]
是不是一个 特殊数组 。
返回布尔数组 answer
,如果 nums[fromi..toi]
是特殊数组,则 answer[i]
为 true
,否则,answer[i]
为 false
。
示例 1:
输入:nums = [3,4,1,2,6], queries = [[0,4]]
输出:[false]
解释:
子数组是 [3,4,1,2,6]
。2 和 6 都是偶数。
示例 2:
输入:nums = [4,3,1,6], queries = [[0,2],[2,3]]
输出:[false,true]
解释:
- 子数组是
[4,3,1]
。3 和 1 都是奇数。因此这个查询的答案是false
。 - 子数组是
[1,6]
。只有一对:(1,6)
,且包含了奇偶性不同的数字。因此这个查询的答案是true
。
提示:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^5
1 <= queries.length <= 10^5
queries[i].length == 2
0 <= queries[i][0] <= queries[i][1] <= nums.length - 1
思路
1.暴力,直接遍历每一个要求的区间,每一个区间都检查一次是否符合要求
2,预处理标定范围,然后每一次查找都是常数时间
首先可以通过定义知道如果数组中存在两个范围,范围内符合要求,那么两个范围一定相邻,
即0110,可以分为01,10 两个合法区域,且不存在一个合法区域介于两个区域之间
那么就可以通过预处理,对处于同一个区域的数据做标记,在查找时比较范围边界是否在相同区域即可,预处理时间复杂度为O(n),单次查找为O(1),全部查找为O(n),则时间复杂度为O(n)
代码
class Solution {
public:vector<bool> isArraySpecial(vector<int>& nums,vector<vector<int>>& queries) {vector<int> temp = vector<int>(nums.size());//预处理结果vector<bool> re = vector<bool>(queries.size());if (nums.size() == 1) {for (int i = 0; i < queries.size(); i++) re[i] = true;return re;}for (int i = 0; i < nums.size() - 1;) {//预处理,将范围的右边界值作为范围标记int k = i;for (int j = i; j < nums.size() - 1; j++) {if ((nums[j] & 1) != (nums[j + 1] & 1))k = j+1;elsebreak;}for (int j = i; j <= k; j++)temp[j] = k;k++;i = k;}if ((nums[nums.size() - 1] & 1) != (nums[nums.size() - 2] & 1))//对最后一个元素进行预处理temp[nums.size() - 1] = temp[nums.size() - 2];elsetemp[nums.size() - 1] = temp[nums.size() - 2] + 1;for (int i = 0; i < queries.size(); i++) {//进行查找,判断指定范围是否合法if (temp[queries[i][0]] == temp[queries[i][1]])re[i] = true;elsere[i] = false;}return re;}
};
看了大佬的代码,感觉自己写的太丑了,靠直觉写出来的东西,还要有边界的单独处理,这里稍作修改
class Solution {
public:vector<bool> isArraySpecial(vector<int>& nums,vector<vector<int>>& queries) {vector<int> temp = vector<int>(nums.size());vector<bool> re = vector<bool>(queries.size());temp[0] = 1;//给一个默认值,没有也可以过,但是最好初始化for (int i = 1; i < nums.size(); i++) {//只需要标记出不同区域即可,此处复杂度减半if ((nums[i] & 1) != (nums[i-1] & 1))temp[i] = temp[i - 1];elsetemp[i] = temp[i - 1] + 1;}for (int i = 0; i < queries.size(); i++) {if (temp[queries[i][0]] == temp[queries[i][1]])re[i] = true;elsere[i] = false;}return re;}
};