当前位置: 首页 > article >正文

leetcode-哈希篇1

leetcode-217

给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

示例 1:

输入:nums = [1,2,3,1]

输出:true

解释:

元素 1 在下标 0 和 3 出现。

示例 2:

输入:nums = [1,2,3,4]

输出:false

解释:

所有元素都不同。

示例 3:

输入:nums = [1,1,1,3,3,4,3,2,4,2]

输出:true

思路:直接用map就可以

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_set<int>us;
        for(auto num : nums){
            if(us.find(num) == us.end()) {
                us.insert(num);
            } else {
                return true;
            }
        }
        return false;
    }
};

leetcode-349

给定两个数组 nums1 和 nums2 ,返回 它们的 

交集

 。输出结果中的每个元素一定是  唯一 的。我们可以  不考虑输出结果的顺序 。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

思路:第一时间想到的是map,但是如果不用map呢,我们是否可以牺牲一点时间复杂度,来换取更少的空间复杂度

没错:使用排序,双指针就可以不用额外空间了

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int>res;
        int i=0, j=0;
        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());
        while(i<nums1.size() && j<nums2.size()) {
            while(i>0 && i < nums1.size() && nums1[i] == nums1[i-1]) {
                ++i;
            }
            if(i >= nums1.size()) {
                break;
            }
            while(j>0 && j < nums2.size() && nums2[j] == nums2[j-1]) {
                ++j;
            }
            if(j >= nums2.size()) {
                break;
            }
            if(nums1[i] == nums2[j]) {
                res.push_back(nums1[i]);
                ++i, ++j;
            } else if(nums1[i] > nums2[j] ) {
                ++j;
            } else {
                ++i;
            }
        }
        return res;
    }
};

leetcode-128

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2:

输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109

思路:先遍历一遍,将所有数放在map里

之后遍历数组,找到一个局部最小数curr(即map里没有cuur-1这个key),逮着这个curr一直向大增长,看他能增长到多少长度,每次保存局部最大长度,选最长的

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_set<int>mp;
        int res = 0;
        for(auto num : nums) {
            mp.insert(num);
        }
        for(auto num : mp) {
            if(!mp.count(num-1)) {
                int dis = 1;
                int curr = num;
                while(mp.count(curr+1)) {
                    ++dis;
                    ++curr;
                }
                res = max(res, dis);
            }
        }
        return res;
    }
};

leetcode-290

给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。

这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。

示例1:

输入: pattern = "abba", s = "dog cat cat dog"
输出: true

示例 2:

输入:pattern = "abba", s = "dog cat cat fish"
输出: false

示例 3:

输入: pattern = "aaaa", s = "dog cat cat dog"
输出: false

思路:使用两个map,你映射我,我映射你,证明我们两是一样的,负责就不是

class Solution {
public:

    vector<string> Split(string strs) {
        vector<string>res;
        string str = "";
        for(auto s : strs) {
            if(s != ' ') {
                str += s;
            } else {
                res.push_back(str);
                str = "";
            }
        }
        if(str != "") {
            res.push_back(str);
        }
        return res;
    }

    bool wordPattern(string pattern, string s) {
        auto strs = Split(s);
        //cout << pattern.size() << ", " << strs.size() << endl;
        if(pattern.size() != strs.size()) {
            return false;
        }
        map<string, char>mp2;
        map<char, string>mp1;
        for(int i=0; i<pattern.size(); i++) {
            if(mp1.find(pattern[i]) == mp1.end()) {
                if(mp2.find(strs[i]) != mp2.end()) {
                    return false;
                }
                mp2[strs[i]] = pattern[i];
                mp1[pattern[i]] = strs[i];
            } else {
                auto str = mp1[pattern[i]];
                if(mp2[strs[i]] != pattern[i]) {
                    return false;
                }
            }
        }
        return true;
    }
};

leetcode-523

给你一个整数数组 nums 和一个整数 k,请你在数组中找出 不同的 k-diff 数对,并返回不同的 k-diff 数对 的数目。

k-diff 数对定义为一个整数对 (nums[i], nums[j]) ,并满足下述全部条件:

  • 0 <= i, j < nums.length
  • i != j
  • |nums[i] - nums[j]| == k

注意|val| 表示 val 的绝对值。

示例 1:

输入:nums = [3, 1, 4, 1, 5], k = 2
输出:2
解释:数组中有两个 2-diff 数对, (1, 3) 和 (3, 5)。
尽管数组中有两个 1 ,但我们只应返回不同的数对的数量。

示例 2:

输入:nums = [1, 2, 3, 4, 5], k = 1
输出:4
解释:数组中有四个 1-diff 数对, (1, 2), (2, 3), (3, 4) 和 (4, 5) 。

示例 3:

输入:nums = [1, 3, 1, 5, 4], k = 0
输出:1
解释:数组中只有一个 0-diff 数对,(1, 1) 。

提示:

  • 1 <= nums.length <= 104
  • -107 <= nums[i] <= 107
  • 0 <= k <= 107

思路:将所有的数放在map里,接着遍历这些数,如果一个数curr满足,curr和curr+k都在该map里,则将该数放入结果中,最终看该结果数组多大

class Solution {
public:
    int findPairs(vector<int>& nums, int k) {
        unordered_set<int>visit;
        unordered_set<int>res;
        for(auto num : nums) {
            if(visit.count(num-k)) {
                res.insert(num-k);
            }
            if(visit.count(num+k)) {
                res.insert(num);
            }
            visit.insert(num);
        }
        return res.size();
    }
};

leetcode-205

给定两个字符串 s 和 t ,判断它们是否是同构的。

如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。

每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。

示例 1:

输入:s = "egg", t = "add"
输出:true

示例 2:

输入:s = "foo", t = "bar"
输出:false

示例 3:

输入:s = "paper", t = "title"
输出:true

提示:

  • 1 <= s.length <= 5 * 104
  • t.length == s.length
  • s 和 t 由任意有效的 ASCII 字符组成

思路:和前面290题目差不多,两个map互相映射

class Solution {
public:
    bool isIsomorphic(string s, string t) {
        if(s.size() != t.size()) {
            return false;
        }
        unordered_map<char, char>mp1;
        unordered_map<char, char>mp2;
        for(int i=0; i<s.size(); i++) {
            if(mp1.find(s[i]) == mp1.end() && mp2.find(t[i]) == mp2.end()) {
                mp1[s[i]] = t[i];
                mp2[t[i]] = s[i];
            } else if(mp1.find(s[i]) != mp1.end() && mp2.find(t[i]) != mp2.end()) {
                if(mp1[s[i]] != t[i] || mp2[t[i]] != s[i]) {
                    return false;
                }
            } else {
                return false;
            }
        }
        return true;
    }
};

leetcode-138

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 

例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。

返回复制链表的头节点。

用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

  • val:一个表示 Node.val 的整数。
  • random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为  null 。

你的代码  接受原链表的头节点 head 作为传入参数。

示例 1:

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

示例 2:

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]

示例 3:

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]

提示:

  • 0 <= n <= 1000
  • -104 <= Node.val <= 104
  • Node.random 为 null 或指向链表中的节点。

思路:这个题目感觉用递归好做些。唯一需要注意的是,需要先复制所有节点本身,再复制随机节点,不然直接复制随机节点,随机节点还没被创建

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;

    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/

class Solution {
public:
    unordered_map<Node*, Node*> mp;
    Node* copyRandomList(Node* head) {
        if (!head) {
            return nullptr;
        }
        if (!mp.count(head)) {
            auto newNode = new Node(head->val);
            mp[head] = newNode;
            newNode->next = copyRandomList(head->next);
            newNode->random = copyRandomList(head->random);
        }
        return mp[head];
    }
};


http://www.kler.cn/news/336991.html

相关文章:

  • String字符串 StringBuilder之常用API
  • 开源模型应用落地-Qwen2.5-7B-Instruct与vllm实现推理加速的正确姿势-Docker-OpenResty(三)
  • 提升 CI/CD 稳定性:Jenkins 开机自检与推送通知
  • macos php开发环境之macport安装的php扩展安装,php常用扩展安装,port中可用的所有php扩展列表
  • C++ 语言特性21 - 别名模板
  • Python 之进阶语法:with...as...
  • ubuntu下vscode插件arm keil studio pack遇到的问题
  • 京东web 京东e卡绑定 第二部分分析
  • OpenCV视频I/O(17)视频写入类VideoWriter之检查视频编写器是否已经成功初始化的函数isOpened()的使用
  • 【QT Quick】C++交互:与QML类型转换
  • macOS开发环境配置与应用开发问题的延伸探讨
  • 什么是安全运营中心 SOC?
  • ARM base instruction -- movk
  • 将自己写好的项目部署在自己的云服务器上
  • Raft 常见问题解答
  • 开源2+1链动S2B2C商城小程序下社区团长的社群温度营造与商业价值实现
  • STM32 通用同步/异步通信
  • 基于SpringBoot图书馆预约与占座小程序【附源码】
  • JS测试框架——Jest
  • selenium元素定位