首页 > 其他分享 >LeetCode---哈希表

LeetCode---哈希表

时间:2024-06-01 14:30:46浏览次数:25  
标签:right set nums int --- vector 哈希 LeetCode left

242. 有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

代码示例: 

//时间复杂度: O(n)
//空间复杂度: O(1)
class Solution {
public:
    bool isAnagram(string s, string t) {
        int hash[26] = {0};
        for (int i = 0; i < s.size(); i++) {
            // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
            hash[s[i] - 'a']++;
        }
        for (int i = 0; i < t.size(); i++) {
            hash[t[i] - 'a']--;
        }
        for (int i = 0; i < 26; i++) {
            if (hash[i] != 0) {
                // record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
                return false;
            }
        }
        // record数组所有元素都为零0,说明字符串s和t是字母异位词
        return true;
    }
};

 349. 两个数组的交集

给定两个数组 nums1 和 nums2 ,返回 它们的 交集。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

代码示例1:(set) 

//时间复杂度: O(n + m) m 是最后要把 set转成vector
//空间复杂度: O(n)
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
        unordered_set<int> nums_set(nums1.begin(), nums1.end());
        for (int num : nums2) {
            // 发现nums2的元素 在nums_set里又出现过
            if (nums_set.find(num) != nums_set.end()) {//若找到,返回该键的元素的迭代器;若没找到,返回set.end();
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(), result_set.end());
    }
};

本题后面 力扣改了 题目描述 和 后台测试数据,增添了 数值范围:

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

所以就可以 使用数组来做哈希表了, 因为数组都是 1000以内的。

代码示例2:(数组)  

//时间复杂度: O(m + n)
//空间复杂度: O(n)
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
        int hash[1005] = {0}; // 默认数值为0
        for (int num : nums1) { // nums1中出现的字母在hash数组中做记录
            hash[num] = 1;
        }
        for (int num : nums2) { // nums2中出现话,result记录
            if (hash[num] == 1) {
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(), result_set.end());
    }
};

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

代码示例1:(暴力解法)  

//时间复杂度:O(n^2),因为在最坏情况下需要检查所有的 n(n-1)/2 对组合。
//空间复杂度:O(1),除了存储结果的向量外,不需要额外的空间。
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result;
        for(int i = 0;i < nums.size();i++){
            for(int j = i+1;j<nums.size();j++){
                if((nums[i] + nums[j]) == target){
                    result.push_back(i);
                    result.push_back(j);
                    return result;
                }
            }
        }
        // 如果没有找到满足条件的结果,返回空结果
        return result;
    }
};

 代码示例2:(map)  

//时间复杂度: O(n)
//空间复杂度: O(n)
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        std::unordered_map <int,int> map;
        for(int i = 0; i < nums.size(); i++) {
            // 遍历当前元素,并在map中寻找是否有匹配的key
            auto iter = map.find(target - nums[i]); 
            if(iter != map.end()) {
                return {iter->second, i};
            }
            // 如果没找到匹配对,就把访问过的元素和下标加入到map中
            map.insert(pair<int, int>(nums[i], i)); 
        }
        return {};
    }
};

454. 四数相加II 

给你四个整数数组 nums1nums2nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

  • 0 <= i, j, k, l < n
  • nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

代码示例: 

//时间复杂度: O(n^2)
//空间复杂度: O(n^2),最坏情况下A和B的值各不相同,相加产生的数字个数为 n^2
class Solution {
public:
    int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
        unordered_map<int, int> umap; //key:a+b的数值,value:a+b数值出现的次数
        // 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中
        for (int a : A) {
            for (int b : B) {
                umap[a + b]++;    //与题242的思路一致
            }
        }
        int count = 0; // 统计a+b+c+d = 0 出现的次数
        // 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。
        for (int c : C) {
            for (int d : D) {
                if (umap.find(0 - (c + d)) != umap.end()) {
                    count += umap[0 - (c + d)];
                }
            }
        }
        return count;
    }
};

15. 三数之和 

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

代码示例: 

//时间复杂度: O(n^2)
//空间复杂度: O(1)
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        // 找出a + b + c = 0
        // a = nums[i], b = nums[left], c = nums[right]
        for (int i = 0; i < nums.size(); i++) {
            // 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了
            if (nums[i] > 0) {
                return result;
            }
            // 错误去重a方法,将会漏掉-1,-1,2 这种情况
            /*
            if (nums[i] == nums[i + 1]) {
                continue;
            }
            */
            // 正确去重a方法
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            int left = i + 1;
            int right = nums.size() - 1;
            while (right > left) {
                // 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right<=left 了,从而漏掉了 0,0,0 这种三元组
                /*
                while (right > left && nums[right] == nums[right - 1]) right--;
                while (right > left && nums[left] == nums[left + 1]) left++;
                */
                if (nums[i] + nums[left] + nums[right] > 0) right--;
                else if (nums[i] + nums[left] + nums[right] < 0) left++;
                else {
                    result.push_back(vector<int>{nums[i], nums[left], nums[right]});
                    // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
                    while (right > left && nums[right] == nums[right - 1]) right--;
                    while (right > left && nums[left] == nums[left + 1]) left++;

                    // 找到答案时,双指针同时收缩
                    right--;
                    left++;
                }
            }

        }
        return result;
    }
};

18. 四数之和 

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abc 和 d 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

代码示例: 

//时间复杂度: O(n^3)
//空间复杂度: O(1)
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        for (int k = 0; k < nums.size(); k++) {
            // 剪枝处理
            if (nums[k] > target && nums[k] >= 0) {
            	break; // 这里使用break,统一通过最后的return返回
            }
            // 对nums[k]去重
            if (k > 0 && nums[k] == nums[k - 1]) {
                continue;
            }
            for (int i = k + 1; i < nums.size(); i++) {
                // 2级剪枝处理
                if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {
                    break;
                }

                // 对nums[i]去重
                if (i > k + 1 && nums[i] == nums[i - 1]) {
                    continue;
                }
                int left = i + 1;
                int right = nums.size() - 1;
                while (right > left) {
                    // nums[k] + nums[i] + nums[left] + nums[right] > target 会溢出
                    if ((long) nums[k] + nums[i] + nums[left] + nums[right] > target) {
                        right--;
                    // nums[k] + nums[i] + nums[left] + nums[right] < target 会溢出
                    } else if ((long) nums[k] + nums[i] + nums[left] + nums[right]  < target) {
                        left++;
                    } else {
                        result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
                        // 对nums[left]和nums[right]去重
                        while (right > left && nums[right] == nums[right - 1]) right--;
                        while (right > left && nums[left] == nums[left + 1]) left++;

                        // 找到答案时,双指针同时收缩
                        right--;
                        left++;
                    }
                }

            }
        }
        return result;
    }
};

 参考如下:

代码随想录

标签:right,set,nums,int,---,vector,哈希,LeetCode,left
From: https://blog.csdn.net/qq_51647149/article/details/139283781

相关文章

  • Go - armv7 交叉编译
    以Ubuntu为例,交叉编译armv7的go程序步骤:安装Golang解压编译工具解压程序交叉编译1.安装Golang从https://go.dev/dl/下载最新的Golang安装包,并解压:sudotar-C/usr/local-xzfgo1.22.3.linux-amd64.tar.gz配置环境变量:exportPATH=$PATH:/usr/local/go/bin也可......
  • GraalVM - Java8 Linux AMD64
    使用GraalVM在linuxamd64环境下编译Java8程序的步骤主要包括:下载GraalVM下载native-image安装native-image编译程序1.下载GraalVM可以通过Github的release页面直接下载(往回找,找到支持java8的graalvm-ce-java8-linux-amd64-20.3.2.tar.gz)https://github.com/graalvm/gra......
  • 1-006 连续因子(分数 20,c++)
    一个正整数 N 的因子中可能存在若干连续的数字。例如630可以分解为3×5×6×7,其中5、6、7就是3个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。输入格式:输入在一行中给出一个正整数 N(1<N<231)。输出格式:首先在第1......
  • 【软件工程】结构化分析与设计——数据流图、SC图、流程图、N-S图
    目录一、数据流图(DFD图)和软件结构图(SC图)1、银行信用卡管理系统——DFD图2、航班信息查询系统——事务型SC图3、成绩管理系统——DFD图、变换型SC图二、流程图和N-S图1、程序N-S图2、判断三角形类型——流程图、N-S图一、数据流图(DFD图)和软件结构图(SC图)1、银行信用......
  • 基于WebSocket的modbus通信(二)- 客户端
    上一篇已经实现了ModbusTcp服务器和8个主要的功能码,只是还没有实现错误处理功能。但是在测试客户端时却发现了上一篇的一个错误,那就是写数据成功,服务器不需要响应。接下来要做的就是实现ModbusTcp客户端。有了清晰的协议,代码循规蹈矩的写就行了。效果原始数据其中只读寄存......
  • css33 CSS Layout - Horizontal & Vertical Align
    https://www.w3schools.com/css/css_align.asp  CenterAlignElementsTohorizontallycenterablockelement(like<div>),usemargin:auto;Settingthewidthoftheelementwillpreventitfromstretchingouttotheedgesofitscontainer.Theele......
  • LLM Fine-Tuning技术笺疏
    LLM训练阶段训练大模型的三个阶段Pre-trainingstage,也就是预训练阶段,其主要目的是「提高对下一个Token的预测能力」。预训练也就是从零开始创建训练大模型的意思,是基于海量文本、几万亿Token进行的,需要上万张GPU。如果你不理解什么是Token,你就把它理解成每个token就是一个英......
  • css32 CSS Layout - display: inline-block
    https://www.w3schools.com/css/css_inline-block.aspThedisplay:inline-blockValueComparedtodisplay:inline,themajordifferenceisthatdisplay:inline-blockallowstosetawidthandheightontheelement.Also,withdisplay:inline-block,thetop......
  • 【Linux】如何利用linux项目自动化构建工具-make/Makefile以及vim编辑器构建两个小程
    1.倒计时小程序首先我们Linux中创建目录test1,该目录中包含了makefile文件,和main.c文件(该文件是源文件用于编写倒计时程序的代码)再进行依赖方法和依赖关系的确定: 利用vim编辑器编辑makefile文件:注意:在依赖方法前面加@的作用是,执行make指令后,将对应的依赖方法不显示在屏幕......
  • LeetCode 第14题:最长公共前缀题目解析(进阶版)
    本文我们来探索LeetCode第14题——最长公共前缀题目解析(进阶版)。文章目录引言题目介绍解题思路思路1:水平扫描法思路2:垂直扫描法思路3:分治法思路4:二分查找法思路5:字典树(Trie)水平扫描法详细解析步骤1:初始化前缀步骤2:逐个比较示例讲解Java代码实现图......