167. 两数之和 II - 输入有序数组


采用方向相反的两个指针来扫遍数组,计算两个元素和:
- 如果大于target,右指针左移
 - 小于target,左指针右移
 - 如果等于的话,返回二者的下标+1
 
class Solution {public:vector<int> twoSum(vector<int>& numbers, int target) {int left = 0, right = numbers.size() - 1;while (left < right) {if (numbers[right] + numbers[left] > target) {right--;} else if (numbers[right] + numbers[left] < target) {left++;} else {return {left + 1, right + 1};}}return {}; // 没找到}};
825. 适龄的朋友
排序+双指针


class Solution {
public:
    int numFriendRequests(vector<int>& ages) {
        // 排序 + 双指针
        sort(ages.begin(), ages.end());
        int left = 0, right = 0, res = 0, n = ages.size();
        // 寻找ages可以发送好友请求的范围
        for (auto age: ages) {
            if (age < 15) {
                continue;
            }
            // left指向第一个满足的元素
            while (left + 1 < n && ages[left] <= 0.5 * age + 7) left++;
            // right指向最后一个满足的元素
            while (right + 1 < n && ages[right + 1] <= age) right++;
            res += right - left; // 这里不用加一,因为本身也在这个区间内,要将其排除
        }
        return res;
    }
};
计数排序+前缀和

class Solution {
public:
    int numFriendRequests(vector<int>& ages) {
        vector<int> cnt(121), pre(121); // 用于计数排序和计算前缀和
        for (auto age: ages) {
            cnt[age]++;
        }
        // 计算前缀和
        for (int i = 1; i < 121; i++) {
            pre[i] = pre[i - 1] + cnt[i];
        }
        int res = 0;
        for (int i = 15; i < 121; i++) {
            if (cnt[i]) {
                int bound = 0.5 * i + 8; // 界向下取整
                res += cnt[i] * (pre[i] - pre[bound - 1] - 1);
            }
        }
        return res;
    }
};
443. 压缩字符串
额外空间
class Solution {
public:
    int compress(vector<char>& chars) {
        if (chars.size() <= 1) return chars.size();
        string res;
        int cnt= 1;
        int i;
        for (i = 1; i < chars.size(); i++) {
            if (chars[i] != chars[i - 1]) {
                res.push_back(chars[i - 1]);
                if (cnt > 1) {
                    res += to_string(cnt);
                    cnt = 1;
                }
            } else {
                cnt++;
            }
        }
        res.push_back(chars[i - 1]);
        if (cnt > 1) {
            res += to_string(cnt);
        }
        for (int i = 0; i < res.size(); i++) {
            chars[i] = res[i];
        }
        return res.size();
    }
};
双指针(快慢/读写双指针)
读写双指针,一个指针往前扫描,查找连续相等的字符的最后一个,写指针记录长度
class Solution {
public:
    int compress(vector<char>& chars) {
        if (chars.size() <= 1) return chars.size();
        int l = 0, n = chars.size(), idx = 0;
        for (int r = 0; r < n; r++) {
            if (r == n - 1 || chars[r] != chars[r + 1]) { // r是临界点
                chars[idx++] = chars[r];
                int len = r - l + 1;
                if (len > 1) {
                    string s = to_string(r - l + 1); // 先转化为字符串,再逐个拷贝
                    for (auto& ch : s) chars[idx++] = ch;
                }
                l = r + 1;
            }
        }
        // 关于字母后面的数字,也可以通过不断取余除以10的办法,添加到chars中,但是添加完毕要翻转一下
        return idx;
    }
};
                    

