每日一题 --- 快乐数[力扣][Go]

快乐数

题目:202. 快乐数

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

「快乐数」 定义为:

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

如果 n快乐数 就返回 true ;不是,则返回 false

示例 1:

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

示例 2:

复制代码
输入:n = 2
输出:false

提示:

  • 1 <= n <= 231 - 1

方法一:

注意无限循环这个词,这代表一个数按照上述操作总会遇到曾经执行过的数。所以有如下写法:

go 复制代码
func isHappy(n int) bool {
	//	定义一个切片存储每次计算后得到的值
	arr := make([]int64, 0)
	// 定义一个map存储各个位数
	m := make(map[int]int64)
	wei := 0
	var sum int64 = 0
	for !isInArr(arr, sum) {
		if sum != 0 {
			arr = append(arr, sum)
			n = int(sum)
			sum = 0
		}

		for n != 0 {
			m[wei] = int64(n) % 10
			n /= 10
			wei++
		}
		wei = 0

		for k, v := range m {
			sum += v * v
			delete(m, k)
		}

		if sum == 1 {
			return true
		}
	}
	return false
}

func isInArr(arr []int64, sum int64) bool {
	for _, i2 := range arr {
		if i2 == sum {
			return true
		}
	}
	return false
}

但是我们使用一个isInArr()函数检查结果是否已经出现过,这明显是浪费时间的。可以改为:使用map集合,结果作为key值,如果曾经存过直接返回false,遇到1返回true。

方法二:

map集合寻找值:

go 复制代码
func isHappy(n int) bool {
	// 定义一个结果集
	res := make(map[int64]struct{})
	// 定义一个map存储各个位数
	m := make(map[int]int64)
	wei := 0
	var sum int64 = 0
	ok := false
	for !ok {
		if sum != 0 {
			res[sum] = struct{}{}
			n = int(sum)
			sum = 0
		}

		for n != 0 {
			m[wei] = int64(n) % 10
			n /= 10
			wei++
		}
		wei = 0

		for k, v := range m {
			sum += v * v
			delete(m, k)
		}

		if sum == 1 {
			return true
		}
		_, ok = res[sum]
	}
	return false
}

这就结束了吗?NoNoNo!

有兴趣的可以看看这个题解:https://leetcode.cn/problems/happy-number/solutions/21454/shi-yong-kuai-man-zhi-zhen-si-xiang-zhao-chu-xun-h

因为不管是不是快乐数,最后总会陷入一个循环,所以我们只需要找出循环就行了。

找循环的方法前几天刚做过,就是快慢指针。

方法三:

go 复制代码
func isHappy(n int) bool {
	// 快慢指针,f走两步,s走一步,如果有循环总会相遇,如果是1,又总会循环
	f, s := n, n
	sn := s
	s = 0
    // Go中不存在do while,所以需要先单独执行一遍,将第一个f==s 跳过
	for sn != 0 {
		s += (sn % 10) * (sn % 10)
		sn /= 10
	}
	for i := 0; i < 2; i++ {
		fn := f
		f = 0
		for fn != 0 {
			f += (fn % 10) * (fn % 10)
			fn /= 10
		}
	}
	for f != s {
		// s 走一步
		sn = s
		s = 0
		for sn != 0 {
			s += (sn % 10) * (sn % 10)
			sn /= 10
		}
		// f走两步

		for i := 0; i < 2; i++ {
			fn := f
			f = 0
			for fn != 0 {
				f += (fn % 10) * (fn % 10)
				fn /= 10
			}
		}
	}
	if f == 1 {
		return true
	} else {
		return false
	}
}
相关推荐
格林威5 小时前
常规线扫描镜头有哪些类型?能做什么?
人工智能·深度学习·数码相机·算法·计算机视觉·视觉检测·工业镜头
程序员莫小特7 小时前
老题新解|大整数加法
数据结构·c++·算法
过往入尘土8 小时前
服务端与客户端的简单链接
人工智能·python·算法·pycharm·大模型
zycoder.8 小时前
力扣面试经典150题day1第一题(lc88),第二题(lc27)
算法·leetcode·面试
Dream it possible!8 小时前
LeetCode 面试经典 150_哈希表_存在重复元素 II(46_219_C++_简单)
leetcode·面试·散列表
蒙奇D索大8 小时前
【数据结构】考研数据结构核心考点:二叉排序树(BST)全方位详解与代码实现
数据结构·笔记·学习·考研·算法·改行学it
智驱力人工智能9 小时前
工厂抽烟检测系统 智能化安全管控新方案 加油站吸烟检测技术 吸烟行为智能监测
人工智能·算法·安全·边缘计算·抽烟检测算法·工厂抽烟检测系统·吸烟监测
学学学无无止境9 小时前
组合两个表-力扣
leetcode
程序员爱钓鱼9 小时前
Go语言实战案例——进阶与部署篇:编写Makefile自动构建Go项目
后端·算法·go
_Power_Y10 小时前
Java面试常用算法api速刷
java·算法·面试