标签 hot100 下的文章

题目链接:找到字符串中所有字母异位词

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

方法:滑动窗口

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        int sl = s.size(),pl = p.size();
        if (sl < pl) {
            return vector<int>();
        }
        vector<int> ans;
        vector<int> sc(26);
        vector<int> pc(26);
        for (int i = 0;i < pl;i++) {
            ++sc[s[i]-'a'];
            ++pc[p[i]-'a'];
        }
        if (sc == pc) {
            ans.push_back(0);
        }
        for (int i = 0;i < sl-pl;i++) {
            --sc[s[i]-'a'];
            ++sc[s[i+pl]-'a'];
            if (sc == pc) {
                ans.push_back(i+1);
            }
        }
        return ans;
    }
};

题目链接:无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。

方法一:暴力?

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int ans = 0;
        
        for (int i = 0;i < s.size();i++) {
            unordered_set<char> occ;
            int num = 1;
            occ.insert(s[i]);
            for (int j = i+1;j < s.size();j++) {
                if (!occ.count(s[j])) {
                    occ.insert(s[j]);
                    num++;
                }else break;
            }
            ans = max(ans,num);
        }
        return ans;
    }
};

方法二:滑动窗口

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_set<char> occ;
        int i = 0;
        int ans = 0;
        int n = s.size();
        for (int j = 0;j < n;j++) {
            while (i < j && occ.count(s[j]) != 0) {
                occ.erase(s[i++]);
            }
            occ.insert(s[j]);
            ans = max(ans,j-i+1);
        }
        return ans;
    }
};

题目链接:接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

方法一:动态规划

class Solution {
public:
    int trap(vector<int>& height) {
        int ans = 0;
        int left_i = 0;
        int right_i[10010];
        for (int i = 0;i < height.size();i++) {
            right_i[i] = 0;
        }
        for (int i = height.size()-2;i >= 0;i--) {
            right_i[i] = max(right_i[i+1],height[i+1]);
        }
        for (int i = 1;i < height.size()-1;i++) {
            int right_i = 0;
            left_i = max(left_i,height[i-1]);
            
            if (left_i > height[i] && right_i[i] > height[i]) {
                ans += min(left_i,right_i[i]) - height[i];
            }
        }
        return ans;
    }
};

方法二:双指针

class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        if (n <= 2) return 0; // 少于3个柱子肯定接不了水

        int left = 0;              // 左指针
        int right = n - 1;         // 右指针
        int left_max = 0;          // 从左往右看到的最高柱子
        int right_max = 0;         // 从右往左看到的最高柱子
        int ans = 0;

        while (left < right) {
            // 谁矮,谁决定当前这边的水位上限
            if (height[left] < height[right]) {
                // 左边更矮,所以水位由左边的最高柱子决定
                if (height[left] >= left_max) {
                    // 更新左边最高柱子
                    left_max = height[left];
                } else {
                    // 左边这个位置可以接的水 = 左边最高 - 当前高度
                    ans += left_max - height[left];
                }
                left++; // 处理完当前 left,往右移
            } else {
                // 右边更矮,水位由右边的最高柱子决定
                if (height[right] >= right_max) {
                    // 更新右边最高柱子
                    right_max = height[right];
                } else {
                    // 右边这个位置可以接的水 = 右边最高 - 当前高度
                    ans += right_max - height[right];
                }
                right--; // 处理完当前 right,往左移
            }
        }

        return ans;
    }
};

题目链接:三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

方法:二分查找

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> ans;
        for (int i = 0;i < nums.size()-2;i++) {
            int x = nums[i];
            int n = nums.size();
            if (i && x == nums[i-1]) continue;
            if (x + nums[i+1] + nums[i+2] > 0) break;
            if (x + nums[n-1] + nums[n-2] < 0) continue;
            int j = i+1,k = n-1;
            while (j < k) {
                int s = x + nums[j] + nums[k];
                if (s > 0) {
                    k--;
                }else if (s < 0) {
                    j++;
                }else {
                    ans.push_back({x,nums[j],nums[k]});
                    for (j++;j < k && nums[j] == nums[j-1];j++);
                    for (k--;k > j && nums[k] == nums[k+1];k--);
                }
            }
        }
        return ans;
    }
};

题目链接:搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

方法:二分查找

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int l = -1,r = nums.size();
        while (l+1 < r) {
            int mid = (l+r)/2;
            if (nums[mid] == target) return mid;
            else if(nums[mid] < target) l = mid;
            else r = mid;
        }
        return r;
    }
};