笔记1 第3课 哈希表——两数之和,模拟行走机器人,字母异位词分组——极客时间算法训练营

之前收藏了极客时间的算法训练营3期 共10周,计划每周内容分3p博客来记录学习,主要形式为

方法类型1

题1

题解

题2

题解

方法类型2

题1

题解

……

题目大体来自leetcode 和 acwing

主要记录和理解代码,所以基本完全搬运了视频题解代码,

个人学习感受体现在大致思路的总结和注释上。


一、哈希表

1.两数之和

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        for(int i = 0; i < nums.size(); i++){
            //哈希表让直接搜索对应数字的复杂度降为O(1)
            if(h.find(target - nums[i]) != h.end()){
                return {h[target-nums[i]], i};
            }
            h[nums[i]]= i;
        }
        return {0};
    }
private:
    unordered_map<int, int> h;
};

2.模拟行走机器人

方向数组

障碍的处理中使用了哈希表。由于不能直接用pair哈希,故设计了到int的哈希、

class Solution {
public:
    int robotSim(vector<int>& commands, vector<vector<int>>& obstacles) {
        int ans = 0;
        for(const vector<int>& ob : obstacles) {
            h.insert(cal({ob[0], ob[1]}));
        }
        int x = 0, y = 0;
        int dir = 0; //N = 0,E = 1, S = 2, W = 3;
        //方向对应的移动指令。
        const int dx[4] = {0, 1, 0 ,-1};
        const int dy[4] = {1, 0, -1, 0};
        for (int command : commands) {
            //注意转向,取余来解决循环;
            if (command == -1){
                dir = (dir + 1) % 4;
            }else if (command == -2){
                dir = (dir + 3) % 4;
            }else{
                for (int i = 0; i < command; i++){
                    int nx = 0,ny = 0;
                    nx = x + dx[dir];
                    ny = y + dy[dir];
                    //查询障碍
                    if(h.find(cal({nx, ny})) != h.end()) break;
                    x = nx;
                    y = ny;
                }
            }
            ans = max(ans, x * x + y * y);
        }
        return ans;
    }
private:
    long long cal (pair<int, int> x) {
        return (x.first + 3 * 1e4) * 6 * 1e4 + x.second + 3 * 1e4;
    }
    unordered_set<long long > h;
};

3.字母异位词分组

把字母排序,存在hash_map 里面,map第二项存答案数组。注意hash_Map的遍历

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        for (string& s : strs) {
            string copy = s;//排序之后会丢失原始数据
            sort(copy.begin(), copy.end());
            groups[copy].push_back(s);
        }
        vector<vector<string>> ans;
        //接下来注意hash——map的遍历方式
        for (const pair<string, vector<string>>& group : groups) {
            ans.push_back(group.second);//把哈希表中存的数组返回
        }
        return ans;
    }
private:
    unordered_map<string , vector<string>> groups;
};

4.串联所有单词的子串

在循环中判定每一个长度和答案相等的串是否可行

判定可行使用哈希表的统计功能,并涉及到2个hash_map的比较问题。

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        int total = 0;
        for (string& word : words) {
            total += word.length();
            wordsMap[word] ++;//建立哈希表,匹配子串。
        }
        vector<int> ans;
        //对于每一个可能的位置判断
        for (int i = 0; i + total <= s.length(); i++){
            if (valid(s.substr(i, total), words)){
                ans.push_back(i);
            }
        }
        return ans;
    }
private: 
    unordered_map<string, int> wordsMap;
    //分组,建立哈希表,并对比哈希表。
    bool valid (string str, vector<string>& words) {
        int k = words[0].length();
        unordered_map<string, int> splitwords;
        for (int i = 0; i < str.length(); i += k) {
            splitwords[str.substr(i, k)] ++;//同建立哈希表
        }
        return equals_map(splitwords, wordsMap);
    }
    bool equals_map (unordered_map<string, int>& a, unordered_map<string, int>& b) {
        //因为数量已经一样了,所以不用翻来覆去的判定两次。
        for (const pair<string, int>& key_and_value : a) {
            const string& key = key_and_value.first;
            const int value = key_and_value.second;
            if(b.find(key) == b.end() || b[key] != value) return false;
        }
        return true;
    }
};

5.. LRU 缓存

最近最少使用,每次使用就提到最前。

题意要求get 和put 在O(1)内完成,故用hash_map来维护k

class LRUCache {
public:
    LRUCache(int capacity) {
        capa = capacity;
        head = new Node();
        tail = new Node();
        head->next = tail;
        tail->pre = head;
    }
    
    int get(int key) {
        if (h.find(key) == h.end()) return -1;
        Node* node = h[key];//把结点提到顶部
        remove(node);
        insert(head, node);
        return node->val;
    }
    
    void put(int key, int value) {
        if (h.find(key) == h.end()) {
            Node* node = new Node();
            node->val = value;
            node->key = key;
            h[key] = node;
            insert(head,node);
            if(h.size() > capa){
                h.erase(tail->pre->key);//删去底部
                remove(tail->pre);
            }
        }else{//更新一下数据放到顶部
            Node* node = h[key];
            node->val = value;
            remove(node);
            insert(head, node);
        }
    }
private:
    int capa;
    struct Node {
        int key;
        int val;
        Node* pre;
        Node* next;
    };
    unordered_map<int, Node*> h;
    Node* head;
    Node* tail;
    void insert (Node* p, Node* node) {
        p->next->pre = node;
        node->next = p->next;
        node->pre = p;
        p->next = node;
    }
    void remove (Node* p) {
        p->next->pre = p->pre;
        p->pre->next = p->next;
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

ey值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值