双指针

  1. 两数之和 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 {};
}
  1. 合并两个有序数组

要从后往前遍历,否则会出现元素覆盖的情况

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--];
    }
}
  1. 环形链表 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;
}
  1. 最小覆盖子串
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);
}
  1. 平方数之和
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;
}
  1. 验证回文串 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;
}
  1. 通过删除字母匹配到字典里最长单词

先将字典按照长度和大小排序,然后找到第一个被包含的字符串(判断某个字符串是否被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 "";
}
  1. 至多包含 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;
}
posted @ 2025-07-15 18:49  dengkang1122  阅读(7)  评论(0)    收藏  举报