【代码随想录】哈希表-golang

news2024/11/26 12:41:08

哈希表 from 代码随想录

hash表解法可以是slice,map…,目的是将时间复杂度降为O(1)

有效的字母异位词

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

排序

思路:直接重新声明字符的字节形式,然后对其进行排序比较

func isAnagram(s, t string) bool {
    if len(s) != len(t) {
        return false
    }
    s1 := []byte(s)
    s2 := []byte(t)
    sort.Slice(s1,func(i,j int) bool{return s1[i] < s1[j]})
    sort.Slice(s2,func(i,j int) bool{return s2[i] < s2[j]})
    return string(s1) == string(s2)
}

哈希表

时间复杂度O(n) n为s的长度
空间复杂度O(s) s为字符集大小

数组

思路:从另一个角度考虑,t 是 s 的异位词等价于「两个字符串中字符出现的种类和次数均相等」。由于字符串只包含 26 个小写字母,声明两个长度为26的数组,遍历s和t后比较两个数组

func isAnagram(s, t string) bool {
    var c1, c2 [26]int
    for _, ch := range s {
        c1[ch-'a']++
    }
    for _, ch := range t {
        c2[ch-'a']++
    }
    return c1 == c2
}

map

思路:先初始化一个map,遍历s去存入然后再遍历t去删除

func isAnagram(s, t string) bool {
    if len(s) != len(t) {
        return false
    }
    s1 := map[rune]int{}
    for _,val := range s {
        s1[val]++
    }
    for _,val := range t {
        s1[val]--
        if s1[val] < 0 {
            return false
        }
    }
    return true

}

两个数组的交集

给定两个数组,编写一个函数来计算它们的交集。

两个集合

如果使用哈希集合存储元素,则可以在 O(1)的时间内判断一个元素是否在集合中,从而降低时间复杂度
时间复杂度和空间复杂度均为O(m+n),其中 m 和 n 分别是两个数组的长度

func intersection(nums1 []int, nums2 []int)(intersection []int) {
    hash1 := map[int]struct{}{}
    hash2 := map[int]struct{}{}
    for _,val := range nums1{
        hash1[val] = struct{}{}
    }
    for _,val := range nums2{
        hash2[val] = struct{}{}
    }
    if len(hash1) > len(hash2){
        hash1,hash2 = hash2,hash1
    }
    for key,_ := range hash1{
        if _,exist := hash2[key];exist{
            intersection = append(intersection,key)
        }
    }
    return 
}

快乐数

编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

func isHappy(n int) bool {
    m := map[int]bool{}
    for ; n!=1 && !m[n];n,m[n] = step(n),true{}
    return n == 1
}
c
func step(n int)int{
    sum := 0
    for n > 0 {
        sum += (n%10) * (n%10)
        n = n/10
    }
    return sum
}

两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。

思路:可以采取暴力解法,双层for循环结束战斗,但是时间复杂度是O(n2),可以采取hash map用空间换时间来降低时间复杂度

func twoSum(nums []int, target int) []int {
    s1 := map[int]int{}
    for index,val := range nums{
        if prevIndex,ok := s1[target - val];ok{
            return []int{prevIndex,index}
        }else{
            s1[val] = index
        }
    }
    return []int{}
}

四数相加II

在这里插入图片描述

将四个数组归为两组 a + b + c + d = 0 --> a + b = -c - d
所以声明一个hashmap将a+b 存入map然后用 -c -d 去命中map
时间复杂度O(n2) 空间复杂度O(n2)

func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int)(ans int)  {
    s1 := map[int]int{}
    for _,a := range nums1 {
        for _,b := range nums2{
            s1[a+b]++
        }
    }
    for _,c := range nums3 {
        for _,d := range nums4{
            ans += s1[-c-d]
        }
    }
    return
}

赎金信

给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。’

(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。杂志字符串中的每个字符只能在赎金信字符串中使用一次。)

思路:类似相同字符串那题?
先通过长度过滤,然后将magazine 中的字符存进hashmap中 val++,遍历赎金信去命中hashmap val-- 如果小于0返回false,未命中返回false,最后返回true

时间复杂度O(m+n),空间复杂度O(n)

hashmap 第一次自解

func canConstruct(ransomNote string, magazine string) bool {
    if len(ransomNote) > len(magazine) {
        return false
    }
    s1 := map[rune]int{}
    for _,val := range magazine{
        s1[val]++
    }
    for _,val := range ransomNote{
        if _,ok := s1[val];ok{
            s1[val]--
            if s1[val] < 0{
                return false
            }
        }else{
            return false
        }
    }
    return true
}

数组,leetcode答案 26长度的数组,用 n - 'a’定位

func canConstruct(ransomNote, magazine string) bool {
    if len(ransomNote) > len(magazine) {
        return false
    }
    cnt := [26]int{}
    for _, ch := range magazine {
        cnt[ch-'a']++
    }
    for _, ch := range ransomNote {
        cnt[ch-'a']--
        if cnt[ch-'a'] < 0 {
            return false
        }
    }
    return true
}

三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。

思路:双指针,固定首个元素然后后两个元素用双指针进行查找,过程中注意检查重复值问题(一旦一个元素重复会造成最后的结果出现重复数组)

func threeSum(nums []int) [][]int {
    n := len(nums)
    sort.Ints(nums)
    ans := make([][]int, 0)
 
    // 枚举 a
    for first := 0; first < n; first++ {
        // 需要和上一次枚举的数不相同
        if first > 0 && nums[first] == nums[first - 1] {
            continue
        }
        // c 对应的指针初始指向数组的最右端
        third := n - 1
        target := -1 * nums[first]
        // 枚举 b
        for second := first + 1; second < n; second++ {
            // 需要和上一次枚举的数不相同
            if second > first + 1 && nums[second] == nums[second - 1] {
                continue
            }
            // 需要保证 b 的指针在 c 的指针的左侧
            for second < third && nums[second] + nums[third] > target {
                third--
            }
            // 如果指针重合,随着 b 后续的增加
            // 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
            if second == third {
                break
            }
            if nums[second] + nums[third] == target {
                ans = append(ans, []int{nums[first], nums[second], nums[third]})
            }
        }
    }
    return ans
}

四数之和

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。

思路:在三数之和的基础上再加上一层for循环

参考答案思路未剪枝版

func fourSum(nums []int, target int)(ans [][]int)  {
    n := len(nums)
    sort.Ints(nums)
    for first := 0;first < n-3 ; first ++ {
        if first > 0 && nums[first] == nums[first - 1]{
            continue
        }
        for second := first + 1;second < n-2 ;second ++ {
            if second > first + 1 && nums[second] == nums[second - 1]{
                continue
            }
            for left,right := second + 1,n - 1;left < right; {
                if sum := nums[first] + nums[second] + nums[left] + nums[right] ;sum == target{
                    ans = append(ans, []int{nums[first], nums[second], nums[left], nums[right]})
                    for left ++ ;left < right && nums[left] == nums[left-1];left++{}
                    for right -- ;left < right && nums[right] == nums[right+1];right--{}
                }else if sum < target{
                    left ++
                }else {
                    right --
                }
            }
        }
    }
    return ans
}

完整版 - 在 first 和 seocnd的for循环中开始剪枝

func fourSum(nums []int, target int)(ans [][]int)  {
    n := len(nums)
    sort.Ints(nums)
    for first := 0;first < n-3 ; first ++ {
    	//去重 + 剪枝
        if first > 0 && nums[first] == nums[first - 1] || nums[first] + nums[n-1] + nums[n-2] + nums[n-3] < target{
            continue
        }
        for second := first + 1;second < n-2 ;second ++ {
        	//去重 + 剪枝
            if second > first + 1 && nums[second] == nums[second - 1] || nums[first] + nums[second] + nums[n-2] + nums[n-1] < target{
                continue
            }
            for left,right := second + 1,n - 1;left < right; {
                if sum := nums[first] + nums[second] + nums[left] + nums[right] ;sum == target{
                    ans = append(ans, []int{nums[first], nums[second], nums[left], nums[right]})
                    for left ++ ;left < right && nums[left] == nums[left-1];left++{}
                    for right -- ;left < right && nums[right] == nums[right+1];right--{}
                }else if sum < target{
                    left ++
                }else {
                    right --
                }
            }
        }
    }
    return ans
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167273.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue的依赖收集和性能问题

什么是依赖收集Vue能够实现当一个数据变更时&#xff0c;视图就进行刷新&#xff0c;而且用到这个数据的其他地方也会同步变更&#xff1b;而且&#xff0c;这个数据必须是在有被依赖的情况下&#xff0c;视图和其他用到数据的地方才会变更。 所以&#xff0c;Vue要能够知道一个…

逻辑思维训练1200题-蓝桥杯计算思维参考

黑格尔曾说过&#xff0c;逻辑是一切思考的基础。逻辑思维能力强的人能迅速、准确地把握住问题的实质&#xff0c;面对纷繁复杂的事情能更容易找到解决的办法。《逻辑思维训练1200 题》介绍了排除法、递推法、倒推法、作图法、假设法、计算法、分析法、类比法、推理法、判断法、…

自动化 | 这些常用测试平台,你们公司在用的是哪些呢?

本文节选自霍格沃兹测试学院内部教材测试管理平台是贯穿测试整个生命周期的工具集合&#xff0c;它主要解决的是测试过程中团队协作的问题。在整个测试过程中&#xff0c;需要对测试用例、Bug、代码、持续集成等等进行管理。下面分别从这四个方面介绍现在比较流行的管理平台。6…

四、template模板

模板 之前的案例中&#xff0c;能够返回简单的字符串信息给浏览器。那如果想要返回html页面给浏览器该怎么做呢&#xff1f; 当然&#xff0c;我们可以这么写&#xff1a; def index(request):return HttpResponse(<h1 style"color:red">我是硬编码的</h…

23年3月如何准备pmp考试?

首先要把PMP考试如何报名、考试内容等都要了解清楚&#xff0c;再去备考。<<PMP入门知识>>PMP考试时长&#xff1a;230分钟。PMP考试形式&#xff1a;笔试。PMP考试题型&#xff1a;题型包括单选题和多选题&#xff0c;多选题将说明需选择几个正确选项。PMP考试题量…

NEUQ week11题解

P1796 汤姆斯的天堂梦 汤姆斯的天堂梦 题目描述 汤姆斯生活在一个等级为 000 的星球上。那里的环境极其恶劣&#xff0c;每天 121212 小时的工作和成堆的垃圾让人忍无可忍。他向往着等级为 NNN 的星球上天堂般的生活。 有一些航班将人从低等级的星球送上高一级的星球&#…

【Java寒假打卡】Java基础-网络编程UDP和TCP

【Java寒假打卡】Java基础-网络编程UDP和TCP网络编程的三要素网络编程的常见命令InetAddress类端口协议UDP发送数据UDP接受数据UDP通信程序的练习TCP通信程序-发送数据TCP通信程序-接受数据网络编程的三要素 网络编程的常见命令 ipconfig 查看本机IP地址ping IP地址&#xff1…

【系列03】方法的学习 方法重载 命令行传参 递归 简单计算机 [有目录]

方法的学习 什么是方法 方法是解决一类问题的步骤的有序组合包含于类或者对象之中方法在程序中被创建,在其他地方被引用 就比如输出方法如:System.out.println(); 就是被封装好的方法 方法设计原则:一个方法完成一个功能,利于后期扩展 [原子性] 使用方法: public class D…

vue中使用echarts 动态渲染数据

一、业务场景&#xff1a; 最近在vue中使用echarts时 引入的时候怎么也引不上&#xff0c;后面发现需要绑定在原型上就可以完美解决(也可以直接在需要引入的页面用ES5中的require引入require&#xff08;‘echarts’&#xff09;) 为了避免大家走弯路&#xff0c;下面整合了一下…

FLStudio水果21最新Daw (宿主软件)电音混音编曲制作工具

对许多音乐爱好者来说&#xff0c;从单独欣赏作品过渡到按自己的心情创作作品&#xff0c;是一种奇妙而令人高兴的体验。 音乐的编曲&#xff0c;特别是电子的编曲&#xff0c;Daw (宿主软件)是重要的要素。 编曲软件有很多。 “专业”这个词取决于你是否在行业的某个部分。 就…

MyBatis 详解 (1) -- 环境搭建、查询操作

MyBatis 详解 1 -- 环境搭建、查询操作一、MyBatis 是什么二、为什么学习 MyBatis三、MyBatis 查询3.1 前言3.2 创建数据库和表3.3 添加 MyBatis 框架支持添加 MyBatis 和 MySQL 驱动3.4 配置连接字符串 和 MyBatis3.4.1 配置连接字符串3.4.2 配置 MyBatis 中的 XML 路径3.5 添…

CSS造成阻塞的原理

目录 1.原理解析 A.webkit渲染过程 B.Gecko渲染过程 C.解析原理 接上篇文章CSS会造成阻塞吗&#xff1f; 我们来说一下CSS造成阻塞的原理 1.原理解析 那么为什么会出现上面的现象呢&#xff1f;我们从浏览器的渲染过程来解析下。 不用浏览器使用的内核不同&#xff0c…

leetcode 648. 单词替换【python3哈希集与两种字典树的方法的思考过程整理】

题目 在英语中&#xff0c;我们有一个叫做 词根(root) 的概念&#xff0c;可以词根后面添加其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如&#xff0c;词根an&#xff0c;跟随着单词 other(其他)&#xff0c;可以形成新的单词 another(另一个)。…

UI自动化测试模块与环境管理全面打通,MeterSphere开源持续测试平台v2.6.0发布

2023年1月16日&#xff0c;MeterSphere一站式开源持续测试平台正式发布v2.6.0版本。 在这一版本中&#xff0c;MeterSphere的UI自动化测试模块与环境管理全面打通&#xff0c;更好地满足了用户一个脚本同时跑多个环境的测试需求。在测试跟踪模块中&#xff0c;测试计划关联测试…

怎么系统的阅读文献

文章目录一、文献阅读1、综述类文献 review article2、研究类文章 research article3、方法学的文章第一部分 综述类文章的阅读第二部分 研究型文章的阅读a. 研究型论文结构b. 如何有选择阅读文献c. 如果整理笔记Citation和Reference的区别二、文献阅读工具1、Connected Papers…

python-while循环

文章目录一、程序的三种结构二、while循环1.1&#xff1a;死循环1.2&#xff1a;循环计数习惯案例1.3&#xff1a;循环计数2.0&#xff1a;break终止循环3.0&#xff1a;人造死循环4.0&#xff1a;continue5.0循环嵌套一、程序的三种结构 1&#xff1a;顺序 代码自上而下执行 …

四旋翼无人机学习第20节--PCB自动保存文件labview设计

0 前言 在设计PCB的过程中&#xff0c;通常一个项目的的PCB文件只有一个&#xff0c;如果保存完文件后想要回滚到自己的版本是比较难的&#xff0c;虽然allergo软件可以设置autosave功能来自动对PCB文件进行备份&#xff0c;但是备份文件只会保存最后一次的版本。 1 labview编…

JavaWeb基础(二) HTTP、Tomcat、Servlet介绍

JavaWeb基础(二) HTTP、Tomcat、Servlet介绍 1&#xff0c;Web概述 1.1 Web和JavaWeb的概念 Web是全球广域网&#xff0c;也称为万维网(www)&#xff0c;能够通过浏览器访问的网站。 在我们日常的生活中&#xff0c;经常会使用浏览器去访问百度、京东、传智官网等这些网站&a…

Dubbo调用

Dubbo调用 0. 概述 Dubbo 服务调用过程比较复杂&#xff0c;包含众多步骤&#xff0c;比如发送请求、编解码、服务降级、过滤器链处理、序列化、线程派发以及响应请求等步骤。 1. 客户端发送请求时序图 InvokerInvocationHandler.invoke 1. 对于Object中的方法toString, has…

IDEA常用配置整理说明

文章目录IDEA常用配置整理说明1、 IDE配置1.1 设置相关1.1.1 忽略大小写开关1.1.2 取消单行显示tabs的操作1.1.3 项目文件编码1.1.4 滚轴修改字体大小1.1.5 设置显示行号和方法间的分隔符1.1.6 新建类头注释信息1.1.7 JavaDoc注释&#xff08;就是方法上加的注释&#xff09;1.…