超级简单分享:快乐数字

天热超级简单分享:快乐数字

介绍

快乐数字是指一个自然数n中的每一位数字的平方和为1或以每一位数字的平方和的结果为新的自然数继续计算平方和直到平方和为1。由于约束条件为自然数,只有两种情况,最终平方和为1,或者几个数出现死循环导致结果永不为1。

Happy number

Input: given a positive integer n.

Ouput: return a boolean type of result whether it is a happy number or not.

Example:

Input: 19
Output: true
Explanation:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1

Input: 11
Output: false
1^2 + 1^2 = 2
2^2 = 4 ------> notice that from here we are starting with 4
4^2 = 16
1^2 + 6^2 = 37
3^2 + 7^2 = 58
5^2 + 8^2 = 89
8^2 + 9^2 = 145
1^2 + 4^2 + 5^2 = 42
4^2 + 2^2 = 20
2^2 + 0^2 = 4 -------> notice that we just get back to 4 again

方法

To calculate the square summation of each digit in each number, the idea is straight forward which is using remainder operator to get the remainder of 10 on a number. By doing this, the last bit digit of the number can be computed (e.g. the remainder of 10 on 124 is 4). Then, the number divided by 10 could get rid of the last digit since it had been already processed (e.g. 124 divided by 10 with integer precision is 12). Using a loop keep doing this could be able to extract each digit in the number. While processing each digit in a number, a summation variable needs to be maintained in order to record the square sum of each digit in the number.
Then the tricky part of this problem how to stop calculating the program. Like the first example which the input is 19. After computing the first number, 19, the result is 82. Since it is not one, the program should not stop. It should keep computing digit square summation of number 82. Then the result is 68 not 1, keep doing. Then the result is 100 not 1, keep doing! Then, the result of 100 is 1 since it is 1^2 + 0 + 0 = 1. The program terminates. If not a happy number, there must be an infinite loop so program will be never terminated if only checking if the result is 1.

Three methods will be introduced on this tricky part. Each has their pros and cons.

  1. A naïve method. A hash data structure will be needed. The idea of this method is to record the history of each number. When the first result is computed and it is not 1, the result would be recorded in a hash table, hash map or hash set. Then when every result is computed, the result will be checked if it is in the hash data structure containing the history value. If it is in a hash data structure, it is a history value meaning it appears before. Therefore, there exists an infinite loop. Program terminates. Otherwise, there is no loop so that the program should keep computing if the next result is equal to 1 or an infinite loop.

  2. Second method would be an easier method using machine learning methodology thought. A threshold will be needed to control the loop. Usually, the loop in this question will be in a small number. Therefore, we could set a threshold to control the loop times. For example, set the threshold to 11, if 1 is not found after the 11th round, program terminates. Then try each number to see if there is any number fail. At the end, the threshold was 20 in my program. It could successfully pass all normal test cases as other methods.

  3. Third method is using Floyd cycle detection algorithm. This is normal algorithm with a pretty good performance on multiple cycle detection problems. The main idea can be vivid stated like 2 people running on the same route, one runs slower and one runs faster.

  4. The route is a cycle like sport ground without destination, the guy who running faster will meet the guy running slower when the faster guy running one more cycle than the slower guy. (not a happy number)

  5. The route is not a cycle and has a destination. The guy who running faster will arrive the destination faster than slower one. (is a happy number and the destination is when result is 1)

Therefore, using 2 pointers, both of them start at the same position. One moves faster which is to compute 2 number in each round. And one moves slower which only computes one number in each round. If they are equal, there is a cycle. If not, check the value of the faster pointer. It will arrive at destination faster so that the running time can be slower.

中文翻译(直译)
要计算每个数字中每个数字的平方和,其思想很简单,即使用余数运算符来得到一个数的10的余数。通过这样做,最后一位数字可以计算数量的剩余部分(例如10 124 4)。然后,数量除以10能摆脱过去的数字,因为它已经处理(例如124除以10个整数精确是12)。使用一个循环,这样做可以提取数字中的每一个数字。在处理数字中的每个数字时,需要维护一个求和变量,以便记录数字中每个数字的平方和。
然后这个问题的棘手部分是如何停止计算程序。比如第一个输入是19的例子。在计算第一个数字19之后,结果是82。既然它不是一个,程序就不应该停止。它应该保持计算82的数字平方和。结果是68不是1,继续。那么结果是100不是1,继续做!那么,100的结果是1,因为它是1^2 + 0 + 0 = 1。程序终止。如果不是一个满意的数字,则必须有一个无限循环,这样,只要检查结果是否为1,程序就永远不会终止。
在这个棘手的部分将介绍三种方法。每个人都有其优点和缺点。

  1. 一个天真的方法。需要一个哈希数据结构。这种方法的思想是记录每个数字的历史。当第一个结果被计算而不是1时,该结果将被记录在一个哈希表、哈希映射或哈希集中。然后,当每个结果被计算时,如果结果在包含历史值的哈希数据结构中,则会检查该结果。如果它是一个哈希数据结构,那么它就是一个历史值,这意味着它出现在前面。因此,存在一个无限循环。程序终止。否则,就没有循环,因此如果下一个结果等于1或无限循环,程序应该继续计算。
  2. 第二种方法是使用机器学习方法思想的一种更简单的方法。需要一个阈值来控制循环。通常,这个问题中的循环次数很少。因此,我们可以设置一个阈值来控制循环时间。例如,将阈值设置为11,如果在第11轮之后没有找到1,则程序终止。然后尝试每个数字,看看是否有任何数字失败。最后,在我的程序中,阈值是20。它可以像其他方法一样成功地通过所有正常的测试用例。
  3. 第三种方法是使用Floyd循环检测算法。这是一个普通的算法,在多周期检测问题上有很好的性能。主要的想法可以生动地陈述,就像2个人在同一条路线上跑,一个跑得慢,一个跑得快。
  4. 路线是一个循环,就像没有目的地的运动场,当跑得快的人比跑得慢的人多跑一个循环时,跑得快的人就会遇到跑得慢的人。(不是一个令人满意的数字)
  5. 这条路线不是一个循环,它有目的地。跑得快的人比跑得慢的人更快到达目的地。(是一个快乐的数字,当结果为1时,目的地为)
    因此,使用两个指针,它们都从相同的位置开始。一是每轮计算2个数字。而每轮只计算一个数字的游戏则运行得更慢。如果它们相等,就有一个循环。如果不是,检查更快指针的值。它将更快地到达目的地,因此运行时间可以更慢。

算法设计

//method 1
public boolean isHappy(int n) {
    Set<Integer> inLoop = new HashSet<Integer>();
    int squareSum,remain;
	while (inLoop.add(n)) {
		squareSum = 0;
		while (n > 0) {
		    remain = n%10;
			squareSum += remain*remain;
			n /= 10;
		}
		if (squareSum == 1)
			return true;
		else
			n = squareSum;

	}
	return false;
}
//method 2
class Solution {
    public boolean isHappy(int n) {
        int sum = 0;
        int num = n;
        int counter = 0;
        while(counter <= 20){
            counter++;
            sum = happyNumber(num);
            if(sum == 1)
                return true;
            if(sum == n)
                return false;
            else
                num = sum;
        }
        return false;
    }
    public int happyNumber(int n){
        int sum = 0;
        while(n != 0){
            int temp = n % 10;
            sum += temp*temp;
            n = n / 10;
        }
        return sum;
    }
}
//method 3
class Solution {
   private int digitSquareSum(int n) {
		int sum = 0, tmp;
		while (n != 0) {
			tmp = n % 10;
			sum += tmp * tmp;
			n /= 10;
		}
		return sum;
	}

	public boolean isHappy(int n) {
		int slow, fast;
		slow = fast = n;
		do {
			slow = digitSquareSum(slow);
			fast = digitSquareSum(fast);
			fast = digitSquareSum(fast);
		} while(slow != fast);
		if (slow == 1) return true;
		else return false;
	}
}

At least one of codes (or more) are 100% original. Some of them are from leetcode since the idea is exactly the same, and the code is almost the same if re-write a new one using the same idea.

算法分析

Computing digit square summation of each number takes number of digits in the number. Since positive integer numbers in the programming language will not contain extremely high # of digits such as 1k digits. It can be seen as constant running time which is O(1).

  1. In method 1, every time the history record will be checked so that the complexity depending on the history list length. However, by using a hash data structure, the searching complexity can be reduced to O(1), the total complexity is number of loop times.
  2. In method 2, everything in the loop takes O(1) time so that the total complexity is number of loop times which is O(t) where t is the threshold.
  3. In method 3, everything in the loop takes O(1) time so that the total complexity is number of loop times.

中文翻译(直译)
计算每个数字的数字平方和需要该数字的位数。因为编程语言中的正整数不会包含非常高的数字#,比如1k位。它可以看作是恒定的运行时间,即O(1)。

  1. 在方法1中,每次都会检查历史记录,以便根据历史记录列表的长度确定复杂性。然而,通过使用哈希数据结构,可以将搜索复杂度降低到O(1),总复杂度为循环次数。
  2. 在方法2中,循环中的所有东西都花费O(1)时间,因此总复杂度是循环次数,即O(t),其中t是阈值。
  3. 在方法3中,循环中的所有东西都花费O(1)的时间,因此总复杂度是循环次数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值