代码随想录 哈希表部分

快乐数

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

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

ini 复制代码
示例 1:
输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:
输入:n = 2
输出:false

思路

首先弄清楚什么时候要用到哈希表(一个元素是否会在集合中重复出现)

然后,此题明显可以把sum重复出现当成无限循环的情况。

即可以简单想到for n!=1 && !m[n]这个循环。

scss 复制代码
   for n!=1 && !m[n]{//给的值不等于1,同时n在m的隐射中不存在
        n,m[n] = getsum(n),true
    }

代码解释

首先,n 的值会被传递给 getSum(n) 函数,并将返回的结果重新赋值给 n。这意味着 n 的值在每次循环迭代时都会更新。

然后,将 true 赋值给 m[n]。根据代码片段提供的信息,m 是一个映射,键的类型可能是 int,值的类型是 bool。这里将键为 n 的值设置为 true,表示 n 已经被访问过。

因此,这段代码的作用是在满足条件 n != 1(n 不等于 1)且 m[n] 为 false(n 在映射 m 中不存在或为 false)时,执行循环体内的代码。在每次循环迭代中,更新 n 的值为 getSum(n) 返回的结果,并将 m[n] 设置为 true。 getsum()就是一个简单求和的函数,不用复述。

俩数之和

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

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

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

ini 复制代码
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]

思路

不用哈希表用最暴力的方法,就是一个一个遍历,然后再后面的数组中查找是否能有相加满足target的数(当初还是萌新的时候的想法)。 代码如下

go 复制代码
func twoSum(nums []int, target int) []int 
{ 
    ans := make([]int, 2)
    for i, x := range nums { //i是索引,x是值
        for j := i + 1; j < len(nums); j++ { 
            if x+nums[j] == target {
                ans[0] = i
                ans[1] =j
                return ans
                } 
             } 
      } return nil
}

今天重刷,当然不能再用以前的方法,考虑使用hash表。

因为代码随想录上面主要还是讲的是c++,所以有些题目可能是用set来完成的。但是go语言是没有set的,所以统一都使用map。(注意map不仅关注元素,还关注下标)

不过go还是支持用map来模拟set的

以下是一些解释:

Set 是一个无序集合,其中每个元素都是唯一的。在 Go 中,可以使用 Map 来模拟 Set,将键作为元素存储在 Map 中,并将值设置为 true 表示元素存在。例如:

arduino 复制代码
set := make(map[int]bool)
set[1] = true
set[2] = true
set[3] = true

Map 是一种键值对形式的数据结构,其中每个键都是唯一的。Map 中的键和值可以是任何类型,因此它更加灵活。与 Set 不同,Map 中的元素是有序的。在 Go 中,可以使用 Map 来存储键值对,例如:

go 复制代码
m := make(map[string]int)
m["apple"] = 1
m["banana"] = 2
m["orange"] = 3

哈希解题

首先肯定还是定义一个map,长度是len(nums) m := make(map[int]int, len(nums))

然后考虑循环条件和循环体。

循环条件:其实没啥,就是读取下标和值 for index,val := range nums

循环体:

css 复制代码
        if j,ok := m[target - val];ok {
            return []int{index, j}
        }
        m[val] = i

代码解释

j, ok := m[target - current] 从 Map m 中查找键为 target - current 的值,同时使用 ok 来判断是否找到了该键。

如果找到了键 target - current,则返回当前元素的索引 i 和找到的索引 j 组成的切片 []int{i, j}

如果没有找到键 target - current,则将当前元素 current 作为键,将其索引 i 作为值存储在 Map m 中,继续遍历数组。

顺带一嘴,下一题竟然不是三数之和(

相关推荐
马剑威(威哥爱编程)1 小时前
除了递归算法,要如何优化实现文件搜索功能
java·开发语言·算法·递归算法·威哥爱编程·memoization
算法萌新——12 小时前
洛谷P2240——贪心算法
算法·贪心算法
湖北二师的咸鱼2 小时前
专题:二叉树递归遍历
算法·深度优先
重生之我要进大厂2 小时前
LeetCode 876
java·开发语言·数据结构·算法·leetcode
KBDYD10103 小时前
C语言--结构体变量和数组的定义、初始化、赋值
c语言·开发语言·数据结构·算法
Crossoads3 小时前
【数据结构】排序算法---桶排序
c语言·开发语言·数据结构·算法·排序算法
自身就是太阳3 小时前
2024蓝桥杯省B好题分析
算法·职场和发展·蓝桥杯
孙小二写代码3 小时前
[leetcode刷题]面试经典150题之1合并两个有序数组(简单)
算法·leetcode·面试
little redcap3 小时前
第十九次CCF计算机软件能力认证-1246(过64%的代码-个人题解)
算法
David猪大卫4 小时前
数据结构修炼——顺序表和链表的区别与联系
c语言·数据结构·学习·算法·leetcode·链表·蓝桥杯