LeetCode刷题记录 36-40

马上要面试了,把前些天在LeetCode上刷的题再看一遍。

写上注释,算复习了,也方便以后复习。

带 * 号的为忘记怎么做的。

36. 1. 两数之和(哈希表)

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> ret;
        int n = nums.size();
        int key;
        unordered_map<int, int> m;
        for (int i = 0; i < n; i++) {
            key = target - nums[i];
            // 如果找到了,就返回
            if (m.find(key) != m.end()) {
                ret.push_back(m[key]);
                ret.push_back(i);
                break;
            }
            // 否则插入当前值
            m.insert(pair<int, int>(nums[i], i));
        }
        return ret;
    }
};

37. 202. 快乐数(哈希表)

class Solution {
public:
    int f(int n) {
        // 计算各位数字平方和
        int sum = 0;
        int temp;
        while (n != 0) {
            temp = n % 10;
            sum += temp * temp;
            n /= 10;
        }
        return sum;
    }

    bool isHappy(int n) {
        if (n == 1) return true;
        unordered_set<int> record;
        int temp = n;
        do {
            // 对一个set进行插入后,如果其second为false,则表明该记录已经存在,插入失败
            if (!record.insert(temp).second) return false;
            temp = f(temp);
        } while (temp != 1);
        return true;   
    }
};

38. 344. 反转字符串(对撞指针)

class Solution {
public:
    void reverseString(vector<char>& s) {
        int n = s.size();
        int left = 0, right = n - 1;
        // 对撞指针
        while (left < right) {
            char temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left ++, right --;
        }
    }
};

39. 209. 长度最小的子数组(滑动窗口)

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size();
        if (n == 0) return 0;
        // 以下初始化,都是基于闭区间[left, right]
        int left = 0, right = 0;
        int sum = nums[0];
        int ans;
        if (sum >= s) ans = 1;  // 不要漏了这种情况
        else ans = n + 1;  // 因为要找最小值,所以初始化为最大值

        while (left < n) {
            // 如果不够,向右扩展
            if (right + 1 < n && sum < s) {
                right ++;
                sum += nums[right];
            }
            // 如果超了,或者到达终点了,左侧缩小,尝试是否出现更优解
            else {
                sum -= nums[left];
                left ++;
            }
            // 更新答案
            if (sum >= s) {
                ans = min(ans, right - left + 1);
            }
        }
        if (ans == n + 1) return 0;
        return ans;
    }
};

40. 76. 最小覆盖子串(滑动窗口)

class Solution {
public:
    string minWindow(string s, string t) {
        int len = s.length();
        // 遍历目标串,知每个字符需要多少个
        unordered_map<char, int> target, window;
        for (char ch : t) target[ch]++;

        int left = 0, right = 0; // 当前窗口为[left..right)
        string ans = "";         // 返回值
        int m = len + 1;         // 长度最小值,初始化为最大值
        int matched = 0;         // 已经匹配的字符个数
        while (right < len) {
            // 处理right号字符
            char chr = s[right];
            // 如果是需要匹配的字符
            if (target.count(chr)) {
                window[chr] ++;
                // 必须是==,才表明是刚达到目标
                if (window[chr] == target[chr]) {
                    matched ++;
                }
            }
            right ++; // 保证当前窗口为[left..right)
            // 尝试更新并缩小最优解
            while (matched == target.size()) {
                // 更新
                if (right - left < m) {
                    m = right - left;
                    ans = s.substr(left, m);
                }
                // 缩小
                char chl = s[left];
                if (target.count(chl)) {
                    window[chl] --;
                    // 必定是==,不过这里换成<target[chl]也可以
                    if (window[chl] == target[chl] - 1) {
                        matched --;
                    }
                }
                left ++;
            }
        }
        return ans;
    }
};
发布了110 篇原创文章 · 获赞 26 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/liujh_990807/article/details/104082392
今日推荐