双指针
- 两数之和 II - 输入有序数组
vector<int> twoSum(vector<int>& numbers, int target) {
int size = numbers.size();
int i = 0, j = size - 1;
while (i < j) {
if (numbers[i] + numbers[j] == target) {
return {i + 1, j + 1};
} else if (numbers[i] + numbers[j] < target) {
i++;
} else {
j--;
}
}
return {};
}
- 合并两个有序数组
要从后往前遍历,否则会出现元素覆盖的情况
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m - 1, j = n - 1, k = m + n - 1;
while (i >= 0 && j >= 0) {
nums1[k--] = nums1[i] >= nums2[j] ? nums1[i--] : nums2[j--];
}
while (j >= 0) {
nums1[k--] = nums2[j--];
}
}
- 环形链表 II
// 解法1:哈希表
ListNode *detectCycle(ListNode *head) {
unordered_set<ListNode *> set;
while (head != nullptr) {
if (set.count(head)) {
return head;
}
set.insert(head);
head = head->next;
}
return nullptr;
}
// 解法2:快慢指针
// 如果链表有环,则fast和slow一定会在环上的某个节点相遇,此时2x-x=n*b(b是环的节点个数),说明slow已经走了n*b步
// 又因为只要slow走的步数满足a+n*b(a是进入环之前的链表节点个数)就可以到达环的入口(即slow只要再走a步就可以到达环的入口)
// 因此将fast重新指向链表的head节点(此时fast也是走a步即可到达环的入口),并每次前进1步
// 当fast和slow再次相遇时,它们一定已经走了a步,并且相遇的点就是环的入口
ListNode *detectCycle(ListNode *head) {
ListNode *slow = head, *fast = head;
do {
if (fast == nullptr || fast->next == nullptr)return nullptr;
fast = fast->next->next;
slow = slow->next;
} while (slow != fast);
fast = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
- 最小覆盖子串
string minWindow(string s, string t) {
// 记录每个字符出现的次数
unordered_map<char, int> char2count;
for (auto& c : t) {
char2count[c]++;
}
int number = 0, index = 0, len = s.size() + 1;
for (int left = 0, right = 0; right < s.size(); ++right) {
if (char2count.count(s[right]) && char2count[s[right]]-- >= 1) {
number++;
}
while (number == t.size()) {
if (right - left + 1 < len) {
index = left;
len = right - left + 1;
}
if (char2count.count(s[left]) && char2count[s[left]]++ >= 0) {
number--;
}
++left;
}
}
return len > s.size() ? "" : s.substr(index, len);
}
- 平方数之和
bool judgeSquareSum(int c) {
int i = 0, j = sqrt(c);
while (i <= j) {
if (i * i == c - j * j)
return true;
else if (i * i < c - j * j)
i++;
else
j--;
}
return false;
}
- 验证回文串 II
bool isValidPalindrome(string s) {
int i = 0, j = s.length() - 1;
while (i <= j) {
if (s[i++] != s[j--])
return false;
}
return true;
}
bool validPalindrome(string s) {
int i = 0, j = s.size() - 1;
while (i <= j) {
if (s[i] == s[j]) {
i++;
j--;
} else {
return isValidPalindrome(s.substr(i, j - i)) ||
isValidPalindrome(s.substr(i + 1, j - i));
}
}
return true;
}
- 通过删除字母匹配到字典里最长单词
先将字典按照长度和大小排序,然后找到第一个被包含的字符串(判断某个字符串是否被s包含可以使用双指针)
string findLongestWord(string s, vector<string>& dictionary) {
sort(dictionary.begin(), dictionary.end(),
[&](const string& a, const string& b) {
if (a.length() != b.length()) {
return a.length() > b.length();
} else {
return a.compare(b) < 0;
}
});
for (auto& word : dictionary) {
int i = 0, j = 0;
while (i < s.length() && j < word.length()) {
if (s[i++] == word[j]) {
j++;
}
}
if (j == word.length())
return word;
}
return "";
}
- 至多包含 K 个不同字符的最长子串
int lengthOfLongestSubstringKDistinct(string s, int k) {
unordered_map<char, int> m;
int res = 0;
for (int left = 0, right = 0; right < s.length(); ++right) {
m[s[right]]++;
while (m.size() == k + 1) {
if (m[s[left]]-- == 1) {
m.erase(s[left]);
}
left++;
}
res = max(res, right - left + 1);
}
return res;
}
浙公网安备 33010602011771号