1、#1550存在连续三个奇数的数组 #数组
时间复杂度o(n),空间复杂度o(1)
①关键:报错,堆缓冲区溢出,内存错误。
解决:把在前面加上int n=arr.size(),后面直接写i<n-2。或者直接在后面写上i+2<arr.size()。
原因:用到size()运算时,因为size()的返回值类型是unsigned int,会把后面的相关运算数-2都强制换成无符号整型,于是报错数组越界。
参考:【LeetCode/C++】循环条件i小于size()-1越界_半盒果酱的博客-优快云博客
②位运算比取模运算快很多,所以写成位运算&1取代%2。
a % (2^n) 等价于 a & (2^n - 1);a % 2 等价于 a & 1
③C++与运算写成&就可以
&与| 既可以进行逻辑运算,又可以进行位运算,两边既可以是bool类型,又可以是数值类型
class Solution {
public:
bool threeConsecutiveOdds(vector<int>& arr) {
/*int n=arr.size();
for(int i=0;i<n-2;++i){*/
for(int i=0;i+2<arr.size();++i){
if((arr[i]&1)&(arr[i+1]&1)&(arr[i+2]&1))return true;
}
return false;
}
};
/*我:
class Solution {
public:
bool threeConsecutiveOdds(vector<int>& arr) {
int n=arr.size();
for(int i=0;i<n-2;++i){
int cnt=0;
for(int j=i;j<i+3;++j){
if(arr[j]%2!=0)++cnt;
}
if(cnt==3)return true;
}
return false;
}
};*/
2、#219 存在重复元素 #数组 #哈希表
时间复杂度o(n),空间复杂度o(min(n,k)),开辟的额外空间取决于散列表中存储的元素的个数,也就是滑动窗口的大小 O(min(n,k))。
????
①关键:用自己的暴力直接求法,不管是把给出的相等和距离的两个条件都用到for循环内,或者把距离用在for条件内、判断相等放在for循环内,不管怎样,用了两个for循环都会超时,光执行时间就是4ms。时间复杂度要么是o(n²),要么是o(nk),总之这样不行,想办法最好是o(n)才可以。
解决:此时就要用另外一种数据结构哈希表,哈希表可以常数时间实现查找,插入,删除等操作。用STL里面的unordered_map容器,其内部实现哈希表,容器元素的排列顺序不同于map,是杂乱无序的,对于查找非常快非常适合,因为键可以不通过搜索就访问无序 map 中的对象,所以可以很快检索出无序 map 中的元素。对于顺序要求高的使用map更适合。
unordered_map将相同哈希值得键值放在相同的桶里。
注意,平时说的vector也是一种容器。STL 是 C++ 标准程序库的核心,STL 组件主要包括容器,迭代器、算法和仿函数。迭代器用于在一个对象群集的元素上进行遍历动作。
②整个过程:比如数组元素有1231,一开始map里面无。当1,map:插入<1,0>,当2,map:插入<2,1>,当3,map:插入<3,2>,当1,map:找到1的键值对为0,此时if可行,算距离为3-0=3,返回true。
③建立基本数据类型的哈希表unordered_map<int,int> map;
map.end()指向哈希表的最后一个容器,实则超出了哈希表的范围,为空
map.find(nums[i]) 查找key为nums[i]数组元素的键值对是否存在 ,未找到则返回map.end()。所以如果==map.end(),则未找到
if(map.find(nums[i])!=map.end()) 说明找到了key为数组元素的键值对。
注意,所有哈希表题目总结参考哈希集合与哈希表的刷题总结_Leopiglet的博客-优快云博客_哈希集合和哈希表
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
unordered_map<int,int> map;// key: 数组元素, value:元素所在下表,注意,此时还没有map键值对
for(int i=0;i<nums.size();i++){
if(map.find(nums[i])!=map.end()&&i-map[nums[i]]<=k){//找到此元素的键值对,会返回当前迭代器,但没找到就会返回map.end(),然后
return true;
}
map[nums[i]]=i;// 这个语句包括两个功能:不是插入,只是把原来那个键值对,更新一下值;插入值,数组访问模式插入(和数组的[]操作很相似)
}
return false;
}
};
/*我:
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
int n=nums.size();
for(int i=1;i<=k;i++){
for(int j=0;j<n-i;j++){
if(nums[j]==nums[j+i])return true;
}
}
return false;
}
};*/
/*class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
int n=nums.size();
for(int i=0;i<n-1;i++){
for(int j=i+1;(j<i+k+1)&(j<n);j++){
if(nums[i]==nums[j])return true;
}
}
return false;
}
};*/
/*class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
for(int i=0;i+1<nums.size();i++){
for(int j=i+1;j<nums.size();j++){
if((nums[i]==nums[j])&(abs(j-i)<=k))return true;
}
}
return false;
}
};*/
总结:在做数组题时,思考时的小tip,先写出一串a1a2a3...这种数组形式,根据题意写出一些遍历的过程,通过遍历的过程去设置无论几个for循环的条件