《LeetCode 热题 100》每日一题

LeetCode 热题 100

目录

LeetCode 热题 100

hash

1. 两数之和

49. 字母异位词分组

128. 最长连续序列

Dual pointers

283. 移动零

11.盛最多水的容器

15. 三数之和

42. 接雨水

sliding window

3. 无重复字符的最长子串

438. 找到字符串中所有字母异位词


hash

1. 两数之和

hash:

image-20231123003040533

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hash;
        vector<int> res;
        for(int i = 0; i < nums.size(); i ++)
        {
            auto t = target - nums[i];
            if(hash.count(t))
            {
                //已经找到配对,hash[t]存的必定是前一个
                res = vector<int> {hash[t], i};
                break;
            }
            else
            {
                hash[nums[i]] = i;
            }
        }
        return res;
    }
};

brute solution:

image-20231123004112846

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> res;
        for(int i = 0; i < nums.size(); i ++)
        {
            for(int j = 0; j < i; j ++)
            {
                if(nums[j] + nums[i] == target)
                {
                    res = vector<int> {j, i};
                    break;
                }
            }
        }
        return res;
    }
};

49. 字母异位词分组

可以复制一份字符串,复制的字符串进行排序,一样的复制字符串加入hash表

emplace_back()push_abck() 的区别是:push_back() 在向 vector 尾部添加一个元素时,首先会创建一个临时对象,然后再将这个临时对象移动或拷贝到 vector 中(如果是拷贝的话,事后会自动销毁先前创建的这个临时元素);而 emplace_back() 在实现时,则是直接在 vector 尾部创建这个元素,省去了移动或者拷贝元素的过程。

hash:

image-20231123151712495

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> map;
        for(string& str:strs)
        {
            string key = str;
            sort(key.begin(), key.end());
            map[key].emplace_back(str);
        }
​
        vector<vector<string>> ans;//变长的变长字符串数组
        for(auto it = map.begin(); it != map.end(); it ++)
        {
            ans.emplace_back(it->second);
        }
        return ans;
    }
};

image-20231123152730286

128. 最长连续序列

hash:

思路和算法

image-20231124143733223

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_set<int> num_set;
        for(auto& num:nums)
        {
            num_set.insert(num);
        }
​
        int Nmax = 0;
​
        for(auto &num:nums)
        {
            if(!num_set.count(num - 1))
            {
                int currentNum = num;
                int currentMax = 1;
​
                while(num_set.count(currentNum + 1))
                {
                    currentNum ++;
                    currentMax ++;
                }
                Nmax = max(Nmax, currentMax);
            }
        }
        return Nmax;
    }
};

image-20231124143814888

brute force:

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        nums.erase(unique(nums.begin(), nums.end()), nums.end());
        int max = 1;
        int cnt = 1;
        for(int i = 0; i < nums.size(); i ++)
        {
            if(i < nums.size() - 1 && nums[i] == nums[i + 1] - 1)
            {
                cnt ++;
                if(cnt > max)
                {
                    max = cnt;
                }
            }
            else
            {
                cnt = 1;
            }
        }
        if(!nums.size()) return 0;
        return max;
    }
};

image-20231123160603955

Dual pointers

283. 移动零

Dual pointers:

283_1.gif

性质:

  • 左指针左边均为非零数;

  • 右指针左边直到左指针处均为零。

    class Solution {
    public:
        void moveZeroes(vector<int>& nums) {
            int n = nums.size(), left = 0, right = 0;
            while(right < n){
                if(nums[right])
                {
                    swap(nums[left], nums[right]);
                    left ++;
                }
                right ++;
            }
        }
    };

    image-20231124150613447

brute force:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        vector<int> res;
        int cnt = 0;
        for(int i = 0; i < nums.size(); i ++)
        {
            if(nums[i])
            {
                res.push_back(nums[i]);
            }
            else
            {
                cnt ++;
            }
        }
        for(int i = 0; i < cnt; i ++)
        {
            res.push_back(0);
        }
        nums = res;
    }
};

image-20231124144555250

11.盛最多水的容器

性质:

  • 面积计算公式:

    S(i,j)=min(h[i],h[j])×(ji)

    Picture0.png

  • 若向内 移动短板 ,下个水槽的面积 可能增大 。

  • 若向内 移动长板 ,下个水槽的面积 一定变小 参考解答

    class Solution {
    public:
        int maxArea(vector<int>& height) {
            int i = 0, j = height.size() - 1, res = 0;
            while(i < j) {
                res = height[i] < height[j] ? 
                    max(res, (j - i) * height[i++]): 
                    max(res, (j - i) * height[j--]); 
            }
            return res;
        }
    };
    //大佬就是叼

    image-20231124152734780

dual pointer:

class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0, right = height.size() - 1;
        int res = 0;
        while(left < right)
        {
            int s = min(height[left], height[right]) * (right - left);
            if(height[right] < height[left])
            {
                res = max(res, s);
                right --;
            }
            else
            {
                res  = max(res, s);
                left ++;
            }
        }
        return res;
    }
};

image-20231124153029338

15. 三数之和

dual pointers:

image-20231128010726178

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        int n = nums.size();
        if(n < 3)
            return res;
        sort(nums.begin(), nums.end());
        for(int i = 0; i < n; i ++)
        {
            if(nums[i] > 0)
                return res;
            if(i > 0 && nums[i] == nums[i - 1])
                continue;
​
            int L = i + 1;
            int R = n - 1;
            while(L < R)
            {
                if(nums[i] + nums[L] + nums[R] == 0)
                {
                    res.push_back({nums[i], nums[L], nums[R]});
​
                    while(L < R && nums[L] == nums[L + 1])
                    {
                        L ++;
                    }
​
                    while(L < R && nums[R] == nums[R - 1])
                    {
                        R --;
                    }
                    L ++;
                    R --;
                }
                else if(nums[i] + nums[L] + nums[R] > 0)
                {
                    R --;
                }
                else
                {
                    L ++;
                }
            }
        }
        return res;
    }
};

42. 接雨水

greedy algorithm:

image-20231128010830988

image-20231128010859251

class Solution {
public:
    int trap(vector<int>& height) {
        int sum = 0;
        int n = height.size();
        if(n == 0)
            return 0;
        vector<int> left_Max(n);
        left_Max[0] = height[0];
        for(int i = 1; i < n; i ++)
        {
            left_Max[i] = max(left_Max[i -  1], height[i]);
        }
​
        vector<int> right_max(n);
        right_max[n - 1] = height[n - 1];
        for(int i = n - 2; i >= 0; i --)
        {
            right_max[i] = max(right_max[i + 1], height[i]);
        }
​
        for(int i = 0; i < n; i ++)
        {
            sum += min(left_Max[i], right_max[i]) - height[i];
        }
​
        return sum;
    }
};

sliding window

3. 无重复字符的最长子串

sliding window:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        // 哈希集合,记录每个字符是否出现过
        unordered_set<char> occ;
        int n = s.size();
        // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
        int rk = -1, ans = 0;
        // 枚举左指针的位置,初始值隐性地表示为 -1
        for (int i = 0; i < n; ++i) {
            if (i != 0) {
                // 左指针向右移动一格,移除一个字符
                occ.erase(s[i - 1]);
            }
            while (rk + 1 < n && !occ.count(s[rk + 1])) {
                // 不断地移动右指针
                occ.insert(s[rk + 1]);
                ++rk;
            }
            // 第 i 到 rk 个字符是一个极长的无重复字符子串
            ans = max(ans, rk - i + 1);
        }
        return ans;
    }
};

image-20231128090157524

438. 找到字符串中所有字母异位词

判断两个字串是不是异位词

  • 长度相同,字母出现的次数相同

S串长度小于P串时,无解

构造一个长度为与字符串 p 的长度相同的滑动窗口,并在滑动中维护窗口中每种字母的数量;当窗口中每种字母的数量与字符串 p 中每种字母的数量相同时,则说明当前窗口为字符串 p 的异位词

以下是力扣大佬的分享

. - 力扣(LeetCode)

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

  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绿皮的猪猪侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值