Day20260303
最长连续序列
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
题解
本题的难度主要在于要用O(n)的方法解决问题。采用的是哈希表的方法。首先用一个hash表记录存在的数值,采用一个<int,bool>的一个哈希表。然后遍历这个哈希表的key,我们要从最小的遍历,即如果key-1 在这个哈希表中,我们那么key一定会被key-1遍历到,所以我们只需要考虑,key-1 不在hash表中的key,然后再遍历,直到key+n不在hash表中。
class Solution {public: int longestConsecutive(vector<int>& nums) {
unordered_map<int,int> ump;
for(int i=0;i<nums.size();i++){ ump[nums[i]] = 1; } int ans = 0; for(auto val:ump){ if(ump.find(val.first-1) != ump.end()) continue; int tmp = 0; int tmpNum = val.first; while(ump.find(tmpNum) != ump.end()){ tmpNum++; tmp++; }
ans = max(ans,tmp); }
return ans;
}};找到字符串中所有字母异位词
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
解答
最容易想到的解法就是完全暴力法,对s中的每个字母,向后截取p个字符,然后看这p个字符是否与p为异位词。复杂度为O(spplog(p)) 。这里判断异位词的方法是排序后判断,我们也可以优化为用一个桶来记录,因为字符就只有26个。然后我们复杂度就被优化为一个O(sp*26)。
然后考虑到对于s的每个字串的桶似乎是有关系的,不需要每个字串都创建一个新的桶,就是把上一个桶的进行部分加减就得到了下个桶,这里复杂度就被优化成了O(s*26)
当然还可以继续优化,这里每次我们都要比较p的桶与s字串的桶,因此会有一个26的较大的常数。为了优化这个常数,我们可以把这两个桶合并为一个桶,p的就是负的,s的字串就是正的,然后维护一个int 类型的diff变量,变量初始化为桶里面每个值的绝对值。然后窗口滑动时再根据逻辑对diff进行加减,最终复杂度也还是O(s)
class Solution {public:
vector<int> findAnagrams(string s, string p) { int sLen = s.size(); int pLen = p.size(); if(sLen < pLen) return vector<int>(0);
vector<int> count(26); vector<int> ans; int differ = 0;
for(int i=0;i<pLen;i++){ count[s[i] - 'a']++; count[p[i] - 'a']--; }
for(int i=0;i<26;i++){ differ += abs(count[i]); }
if(differ==0) ans.push_back(0);
for(int i=pLen;i<sLen;i++){ if(count[s[i]-'a'] < 0){ differ--; }else{ differ++; } count[s[i]-'a']++;
if(count[s[i-pLen]-'a'] > 0){ differ--; }else{ differ++; } count[s[i-pLen]-'a']--; if(differ==0){ ans.push_back(i-pLen+1); } }
return ans;
}};和为k的子数组
给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。
子数组是数组中元素的连续非空序列。
解答
关键在于子数组,连续的一堆值因此考虑前缀和。 如果求出前缀和数组pre 。对任意pre[i] 我们要考虑的就是找出pre数组中是否存在pre[i] - k的值,且这个值必须在i之前出现,出现多少次就会有多少个满足条件的数组。到这里就能联想的两数之和的思路,采用哈希表优化。 从左到右初始化哈希表,因为我们考虑的始终是i左侧的数。
lass Solution {public: int subarraySum(vector<int>& nums, int k) { int len = nums.size(); int ans=0; vector<int> pre(len+1); pre[0] = 0; for(int i=1;i<=len;i++){ pre[i] = pre[i-1] + nums[i-1]; }
unordered_map<int,int> record;
for(int i=0;i<=len;i++){ int target = pre[i] - k; if(record.find(target) != record.end()){ ans += record[target]; }
if(record.find(pre[i]) != record.end()){ record[pre[i]] ++; }else{ record[pre[i]] = 1; } }
return ans; }};