哈希表
其他语言版本
ts-day1
js-day1
python-day1
1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。
链接
题解
该题目的关键在于遍历循环数组,在遍历的过程中,记录目前值与target的差值,且使用map记录差值情况,若存在差值,则直接返回差值
package main
import (
"fmt"
)
func twoSum(nums []int, target int) []int {
hashMap := make(map[int]int)
for i, num := range nums {
// 计算当前值与target的差值
complement := target - num
// 检查差值是否已经在map中
if j, found := hashMap[complement]; found {
// 如果存在该差值,则直接返回[差值对应的下标, 当前值的下标]
return []int{j, i}
}
// 暂时不存在差值,存入当前值的下标
hashMap[num] = i
}
// 如果没有找到任何符合条件的两个数,这里通常应该返回一个错误或空切片,而不是[0, 0]
// 但为了与原始JavaScript函数保持一致,我们返回[0, 0](在实际应用中,这可能不是一个好做法)
return []int{0, 0}
}
func main() {
arr := twoSum([]int{3, 2, 4}, 6)
fmt.Println(arr) // 输出: [1 2]
}
2. 字母异位词分组
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
链接
题解
该题目在于将每一项数据根据Unicode编码排序,异位词经过排序后的字符串会相等,后使用map记录数据即可。
package main
import (
"fmt"
"sort"
"strings"
)
func groupAnagrams(strs []string) [][]string {
// 使用map来存储排序后的字符串作为键,以及一个字符串切片作为值
anagramMap := make(map[string][]string)
for _, str := range strs {
// 将字符串转换为字符切片,排序,然后再转换回字符串
chars := strings.Split(str, "")
sort.Strings(chars)
sortedStr := strings.Join(chars, "")
// 检查map中是否已存在该排序后的字符串
if _, ok := anagramMap[sortedStr]; !ok {
// 如果不存在,则初始化一个新的切片
anagramMap[sortedStr] = []string{}
}
// 将原始字符串添加到对应的切片中
anagramMap[sortedStr] = append(anagramMap[sortedStr], str)
}
// 提取map中的所有值,并转换为二维切片
var result [][]string
for _, value := range anagramMap {
result = append(result, value)
}
return result
}
func main() {
strs := []string{"abc", "cab", "de", "ed"}
result := groupAnagrams(strs)
fmt.Println(result) // 输出: [[abc cab] [de ed]]
}
3.最长连续序列
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
链接
题解:
package main
import (
"fmt"
)
func longestConsecutive(nums []int) int {
// 使用map来模拟集合,存储数组中的唯一元素
numSet := make(map[int]bool)
for _, num := range nums {
numSet[num] = true
}
longestStreak := 0
for num := range numSet {
// 如果num-1不在集合中,那么num可能是连续序列的起点
if !numSet[num-1] {
currentNum := num
currentStreak := 1
// 查找当前连续序列的长度
for numSet[currentNum+1] {
currentNum++
currentStreak++
}
// 更新最长连续序列的长度
if currentStreak > longestStreak {
longestStreak = currentStreak
}
}
}
return longestStreak
}
func main() {
nums := []int{100, 4, 4, 200, 1, 3, 2}
fmt.Println(longestConsecutive(nums)) // 输出: 4
}
指针
4.移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
链接
题解
package main
import (
"fmt"
)
func moveZeroes(nums []int) []int {
if len(nums) == 1 {
return nums
}
left := 0
for right := 0; right < len(nums); right++ {
if nums[right] != 0 {
// 如果右边的元素不是0,并且左边的元素是0,则交换它们
if nums[left] == 0 {
nums[left], nums[right] = nums[right], nums[left]
}
// 将左指针向右移动
left++
}
}
return nums
}
func main() {
arr := []int{0, 1, 0, 3, 12}
moveZeroes(arr)
fmt.Println(arr) // 输出: [1 3 12 0 0]
}
5.盛水最多的容器
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。
说明:你不能倾斜容器。
链接
题解
左右指针法,每次移动短的指针能才有机会使容纳的水变多,因为左右指针收窄时,形成的容器的底是变小的,而能存多少水,容器的高也是一个决定性因素,根据木桶原理,短的木板决定水桶能装多少水,在底变小的情况下,移动短的指针有机会遇到更长的木板,使得容积变大。移动过程中,更新最大值即可。
package main
import (
"fmt"
)
func maxArea(height []int) int {
left := 0
right := len(height) - 1
result := 0
for left < right {
// 底
bottom := right - left
// 高
h := min(height[left], height[right])
// 更新最大值
if area := bottom * h; area > result {
result = area
}
// 根据两边的高度来决定移动哪一边
if height[left] > height[right] {
right--
} else {
left++
}
}
return result
}
// 辅助函数,返回两个整数中的较小值
func min(a, b int) int {
if a < b {
return a
}
return b
}
func main() {
nums := []int{1, 8, 6, 2, 5, 4, 8, 3, 7}
num := maxArea(nums)
fmt.Println(num) // 输出: 49
}
关注我的公众号,回复 100905A1 获取hot100算法在线链接