【Leetcode热题100】

哈希

1. 两数之和

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
    //构建hash表    
    unordered_map<int,int>hash;
    //遍历每个元素数据
    for(int i = 0 ; i < nums.size();++i)
    {
        //目标 - 当前数据 == 与当前设备匹配的元素数据
        auto r = target - nums[i];
        //查询hash表中是否有记载
        if(hash.count(r))return {hash[r] , i};
        //hash表中无记载,把当前数据元素加入到hash表
        hash[nums[i]] = i;
    }
    //没有任何结果返回
    return {};
    }
};

49. 字母异位词分组

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
     //构建哈希表   
    unordered_map<string,vector<string>>hash;
    // 遍历每一个元素
    for (auto &str : strs)
    {
        //将当前元素赋值给新变量
        string nstr = str;
        //重新排序新的变量
        sort(nstr.begin(),nstr.end());
        //将排序后的变量作为key,原始变量作为value
        hash[nstr].push_back(str);
    }
    //上面的操作把每个元素数据进行归一化,下面输出归一化后的结果
    vector<vector<string>>res;
    for(auto &item : hash)res.push_back(item.second);

    return res;


    }
};

128. 最长连续序列

首先将所有数字放入哈希表,遍历哈希表中的元素,因为要找连续的数字序列,因此可以通过向后枚举相邻的数字(即不断加一),判断后面一个数字是否在哈希表中即可。

为了保证O(n)的复杂度,为了避免重复枚举序列,因此只对序列的起始数字向后枚举(例如[1,2,3,4],只对1枚举,2,3,4时跳过),因此需要判断一下是否是序列的起始数字(即判断一下n-1是否在哈希表中)。

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        //构建哈希表,无关顺序
        unordered_set<int> hash(nums.begin(), nums.end());
        int len = 0;
        for (auto num : hash) {
            if (hash.find(num - 1) == hash.end()) { // 只考虑连续序列的起始元素,避免重复遍历序列
                //依次枚举,计算当前长度
                int end = num;
                while (hash.find(end) != hash.end())
                    end += 1;
                len = max(end - num, len);
            }
        }
        return len;
    }
};
双指针

283. 移动零

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
    //索引位置    
    int k = 0;
    //遍历数组,将非0的数移动到数组前面
    for(auto x : nums)
    {
        if(x){
        nums[k++] = x;
        }
    }
    //将剩余的部分补0
    while(k < nums.size()) nums[k++] = 0;
    }
};

11. 盛最多水的容器

class Solution {
public:
    int maxArea(vector<int>& height) {
        //存储全局区间最大值
        int res = 0;
        //使用双指针进行从两边进行扫描处理
        for (int i = 0, j = height.size() - 1; i < j; )
        {
            //使用区间值与当前值做比较,取其中最大值作为最终结果
            res = max(res, 
                min(height[i], height[j]) * (j - i));
            //木桶容量由短板决定, 移动长板的话, 水面高度不可能再上升, 而宽度变小了, 所以只有通过移动短板, 才有可能使水位上升.
            if (height[i] > height[j]) j -- ;
            else i ++ ;
        }
        return res;
    }
};

42. 接雨水

木桶原理,从当前节点往左找最高的高度,往右找最高的高度,这两个高度我们可以看做是木桶的两个木板,能接的雨水由最短的那块决定,累加每个位置能存的雨水量即可。 

class Solution {
public:
    int trap(vector<int>& height) {
        //定义两个从两端的指针
        int l = 0, r = height.size() - 1;
        //定义全局标记结果
        int ans = 0, lmax = 0, rmax = 0;
        while (l < r) {
            //提前更新左右最大值
            lmax = max(lmax, height[l]);
            rmax = max(rmax, height[r]);
            if (lmax < rmax) {
                ans += lmax - height[l];
                l++;
            } else {
                ans += rmax - height[r];
                r--;
            }
        }
        return ans;
    }
};
滑动窗口

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

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
    unordered_map<char,int>hash;
    int res = 0;
    for (int i = 0, j = 0; j < s.size(); j ++ )
    {
    
        hash[s[j]] ++ ;
        
        //只有出现重复情况才会执行while循环
        while (hash[s[j]] > 1) 
        {
       
            //此处--修改string中各位置的对应value减少1,当while停止的时候,i为与j处重复的地方
            hash[s[i ++ ]] -- ; 
 
        }
        /*
        *此处记录当前字符串中的最大字串值,因为数组下标从0开始所以需要加1,这一步每次for都需要执 
        *行,用来实时更新不重复子串的长度
        */
        res = max(res, j - i + 1);
 
    }
    return res;

    }
};

239. 滑动窗口最大值

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        deque<int> q; //双端队列
        vector<int> res;//存储滑动窗口结果
        for(int i = 0; i < nums.size(); i++) //遍历所有元素
        {
            // 处理正常划出队列的情况
            // i 是右端点,那么以k为长度窗口的左端点是i-k+1;
            // 元素淘汰:太靠右的元素 —— 如果左端点比队列的队头要大的话。
            // 说明队头已经过时了,需要划出窗口了。队头就要被删掉
            if(q.size() && i - k + 1 > q.front()) q.pop_front(); // 队列存储的数组的下标

            // 队列内修正的情况
            // 加入当前元素之前,预处理队列
            // 当前元素大于等于队尾元素
            // 删掉队尾
            while (q.size() && nums[i] >= nums[q.back()]) q.pop_back(); //对头插入,队尾删除


            q.push_back(i); //加入当前元素
            if( i >= k -1) res.push_back(nums[q.front()]); //窗口长度满足要求,加入当前的最大元素
        }
        return res;
     }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

༄yi笑奈何

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

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

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

打赏作者

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

抵扣说明:

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

余额充值