六月集训(第05天)—双指针

双指针

1. 2000. 反转单词前缀

    思路:
        遍历找到ch出现的位置r,从0~r翻转word即可。

class Solution {
public:
    string reversePrefix(string word, char ch) {
        int word_len = word.length();
        int l = 0, r = -1, i = 0;
        for (i = 0; i < word_len; ++i) {
            if (ch == word[i]) {
                r = i;
                break;
            }
        }
        if (r == -1) return word;
        while (l < r) {
            swap(word[l++], word[r--]);
        }
        return word;
    }
};

2. 917. 仅仅反转字母

    思路:
        利用l和r两个指针从字符串两端向中间遍历,l++直到s[l]是英文字母暂停,r--直到s[r]为英文字母暂停,交换s[l],s[r]后重复上述操作。

class Solution {
    bool is_english(char ch) {
        if (ch >= 'A' && ch <= 'Z') return true;
        if (ch >= 'a' && ch <= 'z') return true;
        return false;
    }
public:
    string reverseOnlyLetters(string s) {
        int s_len = s.length();
        int l = 0, r = s_len - 1;
        while (l < r) {
            if (!is_english(s[l])) ++l;
            if (!is_english(s[r])) --r;
            if (is_english(s[l]) && is_english(s[r])) {
                swap(s[l], s[r]);
                ++l;
                --r;
            }
        }
        return s;
    }
};

3. 475. 供暖器

    思路:
        对heaters[]排序后,对每个houses[i]二分查找小于houses[i]的最大下标idx
        (1) house两边都有heaters : width_max为 max(width_max, min(houses[i] - heaters[idx], heaters[idx + 1] - houses[i]));
        (2) house只有右边有heaters :即house在heaters[0]左边时,width_max = max(width_max, heaters[0] - houses[i]);
        (3) house只有左边有heaters :即house在heaters[size - 1]右边时 在这里插入代码片


class Solution {
    int find_nearest_less(int l, int r, int ans, vector<int> &heaters) {
        int ret = 0;
        while (l <= r) {
            int mid = l + ((r - l) >> 1);
            if (heaters[mid] <= ans) {
                l = mid + 1;
                ret = mid;
            }
            else r = mid - 1;
        }
        return ret;
    }
public:
    int findRadius(vector<int>& houses, vector<int>& heaters) {
        int houses_size = houses.size(), heaters_size = heaters.size();
        int i;
        int width_max = 0;
        sort(heaters.begin(), heaters.end());
        for (i = 0; i < houses_size; ++i) {
            if (houses[i] <= heaters[0]) {  /* 没有比houses[0]小的元素 */
                width_max = max(width_max, heaters[0] - houses[i]);
                continue;
            }
            int idx = find_nearest_less(0, heaters_size - 1, houses[i], heaters);
            if (idx == -1 || idx == heaters_size - 1) width_max = max(width_max, houses[i] - heaters[idx]); /* houses[i]比所有heaters[]都大,取heaters[size - 1]即可 */
            else {  /* 对于位于两个heaters之间的houses选择左右最近的heater即可 */
                width_max = max(width_max, min(houses[i] - heaters[idx], heaters[idx + 1] - houses[i]));
            }
        }
        return width_max;
    }
};

4. 面试题 16.06. 最小差

    思路:
        思路同第三题,注意强转作差时强转long long否则int溢出。

class Solution {
    #define ll long long
    int find_idx_less(int l, int r, int ans, vector<int> &b) {
        int ret = l;
        while (l <= r) {
            int mid = l + ((r - l) >> 1);
            if (ans >= b[mid]) {
                l = mid + 1;
                ret = mid;
            } else {
                r = mid - 1;
            }
        }
        return ret;
    }
public:
    int smallestDifference(vector<int>& a, vector<int>& b) {
        int a_size = a.size(), b_size = b.size();
        int i = 0, j = 0;
        long long ans = INT_MAX;
        sort(b.begin(), b.end());
        for (i = 0; i < a_size; ++i) {
            if (a[i] <= b[0]) {
                ans = min(ans, ((ll)b[0] - (ll)a[i]));
                continue;
            }
            int idx = find_idx_less(0, b_size - 1, a[i], b);
            if (idx >= b_size - 1) ans = min(ans, ((ll)a[i] - (ll)b[b_size - 1]));
            else ans = min(ans, min(((ll)a[i] - (ll)b[idx]), ((ll)b[idx + 1] - (ll)a[i])));
        }
        return ans;
    }
};
posted @ 2022-06-05 12:06  番茄元  阅读(32)  评论(0)    收藏  举报