欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

LeetCode 202. 快乐数

程序员文章站 2022-05-29 08:35:05
我的LeetCode:https://leetcode cn.com/u/ituring/ 我的LeetCode刷题源码[GitHub]:https://github.com/izhoujie/Algorithmcii LeetCode 202. 快乐数 题目 编写一个算法来判断一个数 n 是不是快 ......

我的leetcode:

我的leetcode刷题源码[github]:https://github.com/izhoujie/algorithmcii

leetcode 202. 快乐数

题目

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

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

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

示例:

输入:19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

来源:力扣(leetcode)
链接:
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

  • 比较容易想到的是顺序计算并判断,因为可能存在循环,所以再额外需要set来保存计算过的值用以后续验重;
  • 另一种思路是快慢指针,因为快乐数的计算最终只会有两种结果:
    • 进入1循环;
    • 进入某循环链无终止循环;
  • 纯数学分析规律,对上面思路更清晰化的解释,即最终的循环结果:
    • 进入1循环;
    • 进入 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4 循环链;

纯数学的分析优化的是非快乐数的循环链,有了链就可以直接建立速查表避免了边计算边存数

思路1-按步骤计算用set保存每次计算结果;

算法复杂度:

  • 时间复杂度: $ {\color{magenta}{\omicron\left(logn\right)}} $
  • 空间复杂度: $ {\color{magenta}{\omicron\left(logn\right)}} $

思路2-建立快慢指针

算法复杂度:

  • 时间复杂度: $ {\color{magenta}{\omicron\left(logn\right)}} $
  • 空间复杂度: $ {\color{magenta}{\omicron\left(1\right)}} $

思路2-数学分析规律建立速查表

算法复杂度:

  • 时间复杂度: $ {\color{magenta}{\omicron\left(logn\right)}} $
  • 空间复杂度: $ {\color{magenta}{\omicron\left(1\right)}} $

算法源码示例

package leetcode;

import java.util.arrays;
import java.util.hashset;

/**
 * @author zhoujie
 * @date 2020年4月30日 下午10:24:08 
 * @description: 202. 快乐数
 *
 */
public class leetcode_0202 {

}

class solution_0202 {
	/**
	 * @author: zhoujie
	 * @date: 2020年4月30日 下午10:53:37 
	 * @param: @param n
	 * @param: @return
	 * @return: int
	 * @description: 快乐数计算
	 *
	 */
	private int happyhelper(int n) {
		int temp = 0;
		while (n > 0) {
			temp += (n % 10) * (n % 10);
			n /= 10;
		}
		return temp;
	}

	/**
	 * @author: zhoujie
	 * @date: 2020年4月30日 下午10:24:31 
	 * @param: @param n
	 * @param: @return
	 * @return: boolean
	 * @description: 1-每次计算后,若为1则是快乐数,否则看是否在set,在则不是快乐数,不在则继续循环计算;(循环有限的,所以代码最后的return其实永远不会执行)
	 *
	 */
	public boolean ishappy_1(int n) {
		hashset<integer> nohappy = new hashset<integer>();
		while (n != 1 && !nohappy.contains(n)) {
			nohappy.add(n);
			n = happyhelper(n);
		}
		return n == 1;
	}

	/**
	 * @author: zhoujie
	 * @date: 2020年4月30日 下午10:36:06 
	 * @param: @param n
	 * @param: @return
	 * @return: boolean
	 * @description: 2-快慢指针;原理:若为1退出循环;若有环,则快指针最终会追上慢指针(多一个循环);
	 *
	 */
	public boolean ishappy_2(int n) {
		int slow = n, fast = happyhelper(n);
		while (slow != fast) {
			if (slow == 1 || fast == 1) {
				return true;
			} else {
				slow = happyhelper(slow);
				fast = happyhelper(happyhelper(fast));
			}
		}
		return slow == 1;
	}

	/**
	 * @author: zhoujie
	 * @date: 2020年4月30日 下午10:45:26 
	 * @param: @param n
	 * @param: @return
	 * @return: boolean
	 * @description: 3-数学规律,任意数最终会进入两个循环,一个是:1自身循环,一个是: 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4
	 *
	 */
	public boolean ishappy_3(int n) {
		// 建立不快乐数的最终循环自查表
		hashset<integer> nohappy = new hashset<integer>(arrays.aslist(4, 16, 37, 58, 89, 145, 42, 20));
		while (n != 1 && !nohappy.contains(n)) {
			n = happyhelper(n);
		}
		return n == 1;
	}
}