【代码随想录——哈希表】

1.哈希表理论基础

首先什么是 哈希表,哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。
在这里插入图片描述
那么哈希表能解决什么问题呢,一般哈希表都是用来快速判断一个元素是否出现集合里。

哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。

2. 有效的字母异位词

在这里插入图片描述

// 判断字符串 t 是否是字符串 s 的字母异位词
func isAnagram(s string, t string) bool {charCount := make(map[rune]int,0)// 若字符串长度不同,直接返回 falseif len(s) != len(t) {return false}// 将字符串转换为字符数组,并对字符数组进行排序sChars := []rune(s)tChars := []rune(t)for i:=0;i<len(sChars);i++{if _,ok:=charCount[sChars[i]];ok{charCount[sChars[i]]++}else{charCount[sChars[i]]=1}}for i:=0;i<len(tChars);i++{char,ok := charCount[tChars[i]]if !ok || char==0{return false}charCount[tChars[i]]--}return true
}

这是官方的一种更简洁的写法:

func isAnagram(s string, t string) bool {if len(s)!=len(t){return false}s_map:=[26]int{}t_map:=[26]int{}for i:=0;i<len(s);i++{s_map[s[i]-'a']++t_map[t[i]-'a']++}return s_map==t_map
}

2.1 字母异位词分组

在这里插入图片描述

2.1.1 第一次的写法,有点慢

func groupAnagrams(strs []string) [][]string {map_style := make([][26]int, 0)str_list := make([][]string, 0)map_index := 0for _, str := range strs {strMap := changeStrToMap(str)index := findCorrectStyle(strMap, map_style, map_index)if index == -1 {//表明这是一个新的stylemap_style = append(map_style, strMap)temp := []string{str}str_list = append(str_list, temp)map_index++} else {str_list[index] = append(str_list[index], str)}}return str_list[0:map_index]
}func changeStrToMap(s string) [26]int {s_map := [26]int{}for i := 0; i < len(s); i++ {s_map[s[i]-'a']++}return s_map
}func findCorrectStyle(strMap [26]int, map_style [][26]int, map_index int) int {for i := 0; i < map_index; i++ {if strMap == map_style[i] {return i}}return -1
}

2.1.2 学习一下高手的写法

确实快,主体思路没什么问题,就是不知道数组也能当做map的key。

func groupAnagrams(strs []string) [][]string {// 没想到数组也可以当做keyhmap := make(map[[26]int][]string)for _, str := range strs {// key 表示str 的字符最多26个,每个字符有多少个key := [26]int{}// 计数for _, ch := range str {// idx 代表字符距离小写字母的距离, b 的话是1idx := ch - 'a'key[idx] ++}hmap[key] = append(hmap[key], str)}result := make([][]string, 0, len(hmap))for _, v := range hmap {result = append(result, v)}   return result
}

2.2 找到字符串中所有字母异位词

在这里插入图片描述

func findAnagrams(s string, p string) []int {res := make([]int, 0)if len(s) < len(p) {return res}// 用来存储p中各个小写字母出现的次数pattern := [26]int{}temp := [26]int{}for i := 0; i < len(p); i++ {pattern[p[i]-'a']++temp[s[i]-'a']++}if pattern == temp {res = append(res, 0)}for i := 0; i < len(s)-len(p); i++ {temp[s[i]-'a']--temp[s[i+len(p)]-'a']++if pattern == temp {res = append(res, i+1)}}return res
}

3. 两个数组的交集

在这里插入图片描述

func intersection(nums1 []int, nums2 []int) []int {mp := make(map[int]struct{},0)res := make([]int,0)// 遍历nums1for _,num := range(nums1){mp[num] = struct{}{}}// 遍历nums2for _,num := range(nums2){_,ok := mp[num]if ok{// 查找到相同元素,加入答案。并从mp中删除res = append(res,num)delete(mp,num)}}return res
}

3.1 两个数组的交集②

在这里插入图片描述
和上面的代码只有一点点区别,区别在于这道题目需要记录元素出现的个数。

func intersect(nums1 []int, nums2 []int) []int {mp := make(map[int]int,0)res := make([]int,0)// 遍历nums1for _,num := range(nums1){_,ok := mp[num]if !ok{mp[num]=1}else{mp[num]++}}// 遍历nums2for _,num := range(nums2){_,ok := mp[num]if ok{// 查找到相同元素,加入答案。并从mp中删除res = append(res,num)mp[num]--if mp[num]==0{delete(mp,num)}}}return res
}

4.快乐数

在这里插入图片描述

func isHappy(n int) bool {mp := make(map[int]struct{},0)for n != 1{_,ok := mp[n]if ok {//这个数见过return false}//没见过,就记录一下mp[n] = struct{}{}n = getSum(n)}return true
}func getSum(n int)int{res := 0for n>0{res = res + (n%10)*(n%10)n = n/10}return res
}

5. 两数之和

在这里插入图片描述

func twoSum(nums []int, target int) []int {m:=make(map[int]int)for i,n:= range nums {j,ok:= m[target-n]if ok {return []int{i,j}}m[n]=i}return []int{}
}

6. 四数相加②

在这里插入图片描述
思路:两两组合

func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {res := 0mp := make(map[int]int,len(nums1)*len(nums1))//循环遍历nums1和nums2两个数组for i:=0;i<len(nums1);i++{for j:=0;j<len(nums2);j++{num := nums1[i] + nums2[j]if _,ok := mp[num];ok{mp[num]++}else{mp[num]=1}}}//循环遍历nums3和nums4两个数组for i:=0;i<len(nums3);i++{for j:=0;j<len(nums4);j++{num := nums3[i] + nums4[j]if _,ok := mp[-num];ok{res += mp[-num]}}}return res
}

7.赎金信

在这里插入图片描述

func canConstruct(ransomNote string, magazine string) bool {pattern1 := [26]int{}for i:=0;i<len(magazine);i++{pattern1[magazine[i]-'a']++}for i:=0;i<len(ransomNote);i++{pattern1[ransomNote[i]-'a']--if pattern1[ransomNote[i]-'a']<0{return false}}return true
}

8.三数之和

在这里插入图片描述
方法一:哈希表

这题不太适合使用hash来做

方法二:双指针,需要先排序。感觉不够快

func threeSum(nums []int) [][]int {var result [][]intif nums == nil || len(nums) < 3 {return result}slices.Sort(nums)for i := 0; i < len(nums); i++ {if nums[i] > 0 {return result}if i > 0 && nums[i] == nums[i-1] {continue}L := i + 1R := len(nums) - 1for L < R {if nums[i]+nums[L]+nums[R] == 0 {sub := []int{nums[i], nums[L], nums[R]}result = append(result, sub)for L < R && nums[L] == nums[L+1] {L += 1}for L < R && nums[R] == nums[R-1] {R -= 1}L += 1R -= 1}else if nums[i]+nums[L]+nums[R] > 0 {R -= 1} else {L += 1}}}return result
}

9.四数之和

在这里插入图片描述

9.1 利用map的写法

我的方法无法通过测试用例,会超时
在这里插入图片描述

func fourSum(nums []int, target int) [][]int {res := make(map[[4]int]struct{}, 0)mp := make(map[int][]int, 0)for i := 0; i < len(nums); i++ {for j := i + 1; j < len(nums); j++ {temp := nums[i] + nums[j]arr, ok := mp[temp]if !ok {slice := make([]int, 2)slice[0] = islice[1] = jmp[temp] = slice} else {//已有arr = append(arr, i)arr = append(arr, j)mp[temp] = arr}}}for key, arr1 := range mp {toFind := target - keyarr2, ok := mp[toFind]if !ok {continue}for i := 0; i < len(arr1)/2; i++ {for j := 0; j < len(arr2)/2; j++ {index_a, index_b := arr1[i*2], arr1[i*2+1]index_c, index_d := arr2[j*2], arr2[j*2+1]if index_a == index_c || index_a == index_d || index_b == index_c || index_b == index_d {continue}item := []int{nums[index_a], nums[index_b], nums[index_c], nums[index_d]}sort.Ints(item)res[[4]int{item[0], item[1], item[2], item[3]}] = struct{}{}}}}back := [][]int{}for key, _ := range res {back = append(back, key[:])}return back
}

9.2 使用双指针的解法

两层for循环,套用一个左右指针。可以通过剪枝提高算法的运行速度。

func fourSum(nums []int, target int) [][]int {if len(nums) < 4 {return nil}sort.Ints(nums)var res [][]intfor i := 0; i < len(nums)-3; i++ {n1 := nums[i]// if n1 > target { // 不能这样写,因为可能是负数// 	break// }if i > 0 && n1 == nums[i-1] {  // 对nums[i]去重continue}for j := i + 1; j < len(nums)-2; j++ {n2 := nums[j]if j > i+1 && n2 == nums[j-1] {  // 对nums[j]去重continue}l := j + 1r := len(nums) - 1for l < r {n3 := nums[l]n4 := nums[r]sum := n1 + n2 + n3 + n4if sum < target {l++} else if sum > target {r--} else {res = append(res, []int{n1, n2, n3, n4})for l < r && n3 == nums[l+1] { // 去重l++}for l < r && n4 == nums[r-1] { // 去重r--}// 找到答案时,双指针同时靠近r--l++}}}}return res
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS实战开发-如何实现查询当前城市实时天气功能

先来看一下效果 本项目界面搭建基于ArkUI中TS扩展的声明式开发范式&#xff0c; 数据接口是和风&#xff08;天气预报&#xff09;&#xff0c; 使用ArkUI自带的网络请求调用接口。 我想要实现的一个功能是&#xff0c;查询当前城市的实时天气&#xff0c; 目前已实现的功能…

水表集中抄表器是什么?什么叫水表集中抄表器?

1.简述 水表集中抄表器是一种智能化的智能设备&#xff0c;主要运用于高效率、清晰地收集管理方法住户或商业客户的用水数据信息。它摒弃了传统的人工抄表方法&#xff0c;完成了远程控制全自动抄表&#xff0c;大大提高了水务管理的效率和精确性。 2.功能特点 2.1实时数据分…

Gradle 进阶学习 之 build.gradle 文件

build.gradle 是什么&#xff1f; 想象一下&#xff0c;你有一个大型的乐高项目&#xff0c;你需要一个清单来列出所有的乐高积木和它们如何组合在一起。在软件开发中&#xff0c;build.gradle 就是这个清单&#xff0c;它告诉计算机如何构建&#xff08;组合&#xff09;你的软…

Python实现txt转Excel(坐标)

import pandas as pddef txt_to_excel(txt_file, excel_file):# 读取 txt 文件with open(txt_file, r) as f:lines f.readlines()# 将每行数据分割成多个单元格data []for line in lines:row line.strip().split( )data.append(row)# 将数据保存到 Excel 文件df pd.DataFra…

麦肯锡精英高效阅读法笔记

系列文章目录 如何有效阅读一本书笔记 读懂一本书笔记 麦肯锡精英高效阅读法笔记 文章目录 系列文章目录序章 无法读书的5个理由无法读书的理由① 忙于工作&#xff0c;没时间读书无法读书的理由② 不知应该读什么无法读书的理由③ 没读完的书不断增多无法读书的理由④ 工作繁…

LeetCode面试298,二叉树最长连续序列(Python)

开始想着dfs&#xff0c;两种情况 1.以root为根 2.不以root为根 但是这样需要两个dfs分别进行&#xff0c;那么时间复杂度就上去了。 class Solution:def longestConsecutive(self, root: Optional[TreeNode]) -> int:def dfs(root):# 以root为根节点&#xff0c;可以延…

视频素材库在哪里找免费手机版?8个可以用手机浏览的素材网

在视觉内容占据主导地位的今天&#xff0c;合适的视频素材可以大大提升项目的吸引力和效果。以下列出的视频素材网站为广告制作者、社交媒体策略师及电影制作人提供了从传统到现代风格的各种视频素材选择&#xff0c;满足不同的创作需求。 1. 蛙学府&#xff08;中国&#xff…

关系型数据库MySQL开发要点之多表设计案例详解代码实现

什么是多表设计 项目开发中 在进行数据库表结构设计时 根据数据模型和业务关系 会根据业务需求和业务模块之间的关系分析设计表结构 由于业务之间互相关联 所以表结构之间也存在着各种联系 主要分为以下三种 一对多 每个部门下是有多个员工的 但是一个员工只能归属一个部…

Linux —— 信号(3)

Linux —— 信号&#xff08;3&#xff09; Core dump为什么core默认是被关闭的阻塞信号信号其他相关常见概念信号递达信号未决信号阻塞两者的区别信号的结构 信号集操作函数一个简单使用例子sigpending的使用例子 我们今天接着来了解信号&#xff1a; Core dump 大家不知道有…

6.移除元素

文章目录 题目简介题目解答解法一&#xff1a;双指针代码&#xff1a;复杂度分析&#xff1a; 解法二&#xff1a;双指针优化代码&#xff1a;复杂度分析&#xff1a; 题目链接 大家好&#xff0c;我是晓星航。今天为大家带来的是 相关的讲解&#xff01;&#x1f600; 题目简…

6W 1.5KVDC. 单、双输出 DC/DC 电源模块——TP2L-6W 系列

TP2L-6W系列是一款高性能、超小型的电源模块&#xff0c;2:1电压输入&#xff0c;输出有稳压和连续短路保护功能&#xff0c;隔离电压为1.5KVDC、作温度范围为–40℃到85℃。特别适合对输出电压的精度有严格要求的地方&#xff0c;外部遥控功能对您的设计又多一项选择&#xff…

25考研英语长难句Day02

25考研英语长难句Day02 【a.词组】【b.断句】 如果你是你讲话对象中的一员&#xff0c;你就能了解你们大家共同的经历和问题&#xff0c;你也可以顺便评论一下食堂里难吃的食物或董事长臭名昭著的领带品味。 【a.词组】 单词解释addressv. 演说&#xff0c; 演讲&#xff1b;…