滑动窗口题
LC3 LC424
https://leetcode-cn.com/problems/longest-repeating-character-replacement/solution/fen-xiang-zhen-cang-de-shuang-zhi-zhen-m-fdsk/
首先需要区分两个概念:子串(子数组) 和 子序列。这两个名词经常在题目中出现,非常有必要加以区分。子串sub-string(子数组 sub-array)是连续的,而子序列 subsequence 可以不连续。
3. 无重复字符的最长子串
难度中等4905
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
class Solution {public:int lengthOfLongestSubstring(string s) {int n = s.size();int left = 0, right = 0;int ans = 0;unordered_set<char> mem;while(right < n){while(mem.count(s[right])){mem.erase(s[left]);left++;}ans = max(ans, right - left + 1);mem.emplace(s[right]);right ++;}return ans;}};
424. 替换后的最长重复字符
难度中等281
给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。
注意:字符串长度 和 k 不会超过 104。
class Solution {public:int characterReplacement(string s, int k) {int n = s.size();int left = 0, right = 0;int maxnow = 0;int ans = 0;vector<int> mem(26);//右指针维护while(right < n){mem[s[right] - 'A'] ++ ;maxnow = max(maxnow, mem[s[right] - 'A']);//移动left到满足题目条件为止//本题即是用总长度减去最大出现的数字个数//令剩下数字的数量要小于kwhile(right - left + 1 - maxnow > k){mem[s[left] - 'A'] --;left ++;}ans = max(ans, right - left + 1);right ++;}return ans;}};
以上两题大体模版相同 只在根据题意判断是否符合并且移动左指针时有所不同。
30. 串联所有单词的子串
难度困难409
给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
class Solution {public:vector<int> findSubstring(string s, vector<string>& words) {int n = s.size();int word_len = words[0].size(), all_len = words.size();vector<int> ans;int left = 0, right;//记录原wordsunordered_map<string, int> mem;for(auto& c: words)mem[c] ++;unordered_map<string, int> window;for(int i = 0; i < word_len; ++ i){while(left + word_len * all_len <= n){right = left;while(right <= n){if(mem == window){ans.push_back(left);}string ns = s.substr(right, word_len);window[ns] ++;//不存在或次数超过if(!mem.count(ns)) break;if(window[ns] > mem[ns]) break;right += word_len;}window.clear();left ++;}}return ans;}};
995. K 连续位的最小翻转次数
难度困难181
在仅包含 0 和 1 的数组 A 中,一次 _K_ 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0。
返回所需的 K 位翻转的最小次数,以便数组没有值为 0 的元素。如果不可能,返回 -1。
示例 1:
输入:A = [0,1,0], K = 1
输出:2
解释:先翻转 A[0],然后翻转 A[2]。
示例 2:
输入:A = [1,1,0], K = 2
输出:-1
解释:无论我们怎样翻转大小为 2 的子数组,我们都不能使数组变为 [1,1,1]。
示例 3:
输入:A = [0,0,0,1,0,1,1,0], K = 3
输出:3
解释:
翻转 A[0],A[1],A[2]: A变成 [1,1,1,1,0,1,1,0]
翻转 A[4],A[5],A[6]: A变成 [1,1,1,1,1,0,0,0]
翻转 A[5],A[6],A[7]: A变成 [1,1,1,1,1,1,1,1]
提示:
1 <= A.length <= 300001 <= K <= A.length
双指针包括快慢指针和左右指针,其实滑动窗口也是一种双指针,但是几种方法的适用情况都不同。
class Solution {public:int minKBitFlips(vector<int>& A, int K) {int n = A.size();int ans = 0;int right = 0;//用队列来模拟滑动窗口//存的是下标,表示的是哪些位置(在k范围内)进行翻转//那么队列的大小n就表示了前k个单位中要翻转几次//那么n为偶数时当前的数就等于没有翻转,为奇数则翻转queue<int> que;while(right < n){//无法再翻转,或者过了要翻转的数字距离if(!que.empty() && right >= que.front() + K)que.pop();//综合得出的结论,要翻转,记录if(que.size() % 2 == A[right]){if(right + K > n)return -1;que.push(right);ans ++;}right ++;}return ans;}};
剑指 Offer II 015. 字符串中的所有变位词
class Solution {public:vector<int> findAnagrams(string s, string p) {vector<int> ans;int sLen = s.size(), pLen = p.size();if(sLen < pLen){return {};}vector<int> sCount(26, 0);vector<int> pCount(26, 0);for(int i = 0; i < pLen; ++ i){sCount[s[i] - 'a'] ++;pCount[p[i] - 'a'] ++;}if(sCount == pCount){ans.push_back(0);}for(int i = 0; i < sLen - pLen; ++ i){sCount[s[i] - 'a'] --;sCount[s[i + pLen] -'a'] ++;if(sCount == pCount){ans.push_back(i + 1);}}return ans;}};
双指针题
11. 盛最多水的容器
难度中等2235
给你 n 个非负整数 a1,a2,...,a``n,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1]
输出:1
示例 3:
输入:height = [4,3,2,1,4]
输出:16
示例 4:
输入:height = [1,2,1]
输出:2
提示:
n = height.length2 <= n <= 3 * 1040 <= height[i] <= 3 * 104class Solution {public:int maxArea(vector<int>& height) {int res = 0;int n = height.size();int left = 0, right = n - 1;while(left < right){int high = min(height[left], height[right]);int width = right - left;res = max(res, high * width);if(height[left] == high){left ++;}else{right --;}//好像不是很能找到滑动的情况// if(height[left] == high){// left ++;// }}return res;}};
15. 三数之和
难度中等3030
给你一个包含n个整数的数组nums,判断nums中是否存在三个元素 a,b,c ,使得 _a + b + c = _0 ?请你找出所有和为0且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]class Solution {public:vector<vector<int>> threeSum(vector<int>& nums) {int n = nums.size();vector<vector<int> > ans;if(n < 2) return ans;sort(nums.begin(), nums.end());for(int i = 0; i < n - 2; ++ i){if(nums[i] > 0)break;if(i > 0 && nums[i] == nums[i - 1]) continue;int low = i + 1, high = n - 1;while(low < high){int temp = nums[i] + nums[low] + nums[high];if(temp == 0){ans.push_back({nums[i], nums[low], nums[high]});while(low < high && nums[low] == nums[low + 1]) low ++;while(low < high && nums[high] == nums[high - 1]) high --;low ++;high --;}if(temp < 0) low ++;if(temp > 0) high --;}}return ans;}};
75. 颜色分类
难度中等801
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
示例 1:
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
示例 2:
输入:nums = [2,0,1]
输出:[0,1,2]
示例 3:
输入:nums = [0]
输出:[0]
示例 4:
输入:nums = [1]
输出:[1]
class Solution {public:void sortColors(vector<int>& nums) {int n = nums.size();int p0 = 0, p2 = n - 1;int i = 0;while(i <= p2){if(nums[i] == 0){swap(nums[i], nums[p0]);p0 ++;//这里必须要i++, 因为p0必然是1,如果是2的话已经被换再i后面了,这点是可以保证的i ++;}else if(nums[i] == 1){i ++;}else{swap(nums[i], nums[p2]);p2 --;//这里不要i++ 因为我们只能保证nums[i] == 2,但是不能保证nums[p2] == 1}}}};
141. 环形链表
难度简单986
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:**pos** 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
提示:
- 链表中节点的数目范围是
[0, 104] -105 <= Node.val <= 105pos为-1或者链表中的一个 有效索引 。/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/class Solution {public:bool hasCycle(ListNode *head) {if(!head || !head->next){return false;}ListNode* slow = head;ListNode* quick = head->next;while(slow != quick){if(!quick || !quick->next){return false;}slow = slow->next;quick = quick->next->next;}return true;}};
142. 环形链表 II
难度中等912
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回null。
为了表示给定链表中的环,我们使用整数pos来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果pos是-1,则在该链表中没有环。注意,**pos**仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
进阶:你是否可以使用
O(1)空间解决此题?
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
提示:
- 链表中节点的数目范围在范围
[0, 104]内 -105 <= Node.val <= 105pos的值为-1或者链表中的一个有效索引/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/class Solution {public:ListNode *detectCycle(ListNode *head) {if(head == nullptr){return nullptr;}ListNode* slow = head;ListNode* fast = head;while(fast != nullptr){slow = slow->next;if(fast->next == nullptr){return nullptr;}fast = fast->next->next;if(slow == fast){//利用公式a = c + (n - 1)(b + c)ListNode* p = head;while(p != slow){p = p->next;slow = slow->next;}return slow;}}return nullptr;}};
