202. Happy Number

题目:

Write an algorithm to determine if a number is "happy".

A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.

Example: 19 is a happy number

  • 12 + 92 = 82
  • 82 + 22 = 68
  • 62 + 82 = 100
  • 12 + 02 + 02 = 1

链接: http://leetcode.com/problemset/algorithms/

题解:

判断一个数字是否为Happy Number。这道题跟求无限循环小数很像,最好维护一个HashSet,假如遇见重复,则返回false。否则替换n为digits square root sum,当n == 1时循环结束返回true。

Time Complexity - O(n), Space Complexity - O(n)。

public class Solution {
    public boolean isHappy(int n) {
        if(n <= 0)
            return false;
        Set<Integer> set = new HashSet<>();
        
        while(n != 1) {
            if(set.contains(n))
                return false;
            else {
                set.add(n);
                n = getSquareSumOfDigits(n);
            }
        }
        
        return true;
    }
    
    private int getSquareSumOfDigits(int n) {
        int res = 0;
        
        while(n > 0) {
            res += (n % 10) * (n % 10);
            n /= 10;
        }
        
        return res;
    }
}

 

二刷:

就是在i != 1的情况对n进行处理,使用一个Set来保存出现过的数字,假如重复则出现循环,这时候我们return false。否则跳出循环的时候n == 1,我们return true。

Java:

Time Complexity - O(n), Space Complexity - O(n)。  时间复杂度和空间复杂度需要用数学公式来推算。这公式是什么我现在也不知道。

public class Solution {
    public boolean isHappy(int n) {
        if (n < 1) {
            return false;
        }
        Set<Integer> set = new HashSet<>();
        set.add(n);
        int newNum = 0;
        while (n != 1) {
            while (n != 0) {
                newNum += (n % 10) * (n % 10);
                n /= 10;
            }
            if (!set.add(newNum)) {
                return false;
            }
            n = newNum;
            newNum = 0;
        }
        return true;
    }
}

 

 

题外话: 今天试了一下Coursera的Crytography I,感觉难度比较大,需要很好的概率知识。做作业的时候参考了别人在github上写的Python代码,好简洁。自己也要好好练起来。又发现了几个比较优美的算法课件,都是来自Kevin Wayne,要好好看一看。其实至今为止自己收集了很多资料,包括书籍,课件,Source Code, Video等等,但总觉得没准备好,心里没底,也许是因为这leetcode到现在第一遍还没完成吧。说不定真刷到了5遍7遍的,融会贯通了以后,才会安心一点。

 

三刷:

Java:

public class Solution {
    public boolean isHappy(int n) {
        if (n < 1) {
            return false;
        }
        Set<Integer> set = new HashSet<>();
        set.add(n);
        while (n != 1) {
            n = getSquareSum(n);
            if (!set.add(n)) {
                return false;
            }
        }
        return true;
    }
    
    private int getSquareSum(int num) {
        int res = 0;
        while (num != 0) {
            int remainder = num % 10;
            res += remainder * remainder;
            num /= 10;
        }
        return res;
    }
}

 

Update:

public class Solution {
    public boolean isHappy(int n) {
        if (n < 1) return false;
        Set<Integer> set = new HashSet<>();
        while (n != 1) {
            int num = 0;
            while (n != 0) {
                num += (n % 10) * (n % 10);
                n /= 10;
            }
            if (!set.add(num)) return false;
            n = num;
        }
        return true;
    }
}

 

 

更好的解可以把Space Complexity 简化到 O(1),使用 fast / slow pointer进行Cycle Detection的思路,很巧妙。 更奇妙的是运行时间也减少了。 

 

public class Solution {
    public boolean isHappy(int n) {
        if (n < 1) {
            return false;
        }
        int x = n, y = getDigitSquareSum(n);
        while (x != y) {
            x = getDigitSquareSum(x);
            y = getDigitSquareSum(getDigitSquareSum(y));
           
        }
        return x == 1;
    }
    
    private int getDigitSquareSum(int n) {
        int res = 0;
        while (n > 0) {
            int curDigit = n % 10;
            res += curDigit * curDigit;
            n /= 10;
        }
        return res;
    }
}

 

Update:

public class Solution {
    public boolean isHappy(int n) {
        if (n < 1) return false;
        int slow = n, fast = getSquareSum(n);
        while (slow != fast) {
            slow = getSquareSum(slow);
            fast = getSquareSum(getSquareSum(fast));
        }
        return slow == 1;
    }
    
    private int getSquareSum(int n) {
        int num = 0;
        while (n != 0) {
            num += (n % 10) * (n % 10);
            n /= 10;
        }
        return num;
    }
}

 

四刷:

class Solution {
    Set<Integer> set = new HashSet<>();
    
    public boolean isHappy(int n) {
        if (n < 1) return false;
        if (set.contains(n)) return n == 1;
        else set.add(n);
        return isHappy(getSquareSum(n));
    }
    
    private int getSquareSum(int n) {
        int num = 0;
        while (n != 0) {
            num += (n % 10) * (n % 10);
            n /= 10;
        }
        return num;
    }
}

 

 

 

Reference:

https://leetcode.com/discuss/33055/my-solution-in-c-o-1-space-and-no-magic-math-property-involved

https://leetcode.com/discuss/71625/explanation-those-posted-algorithms-mathematically-valid

https://leetcode.com/discuss/33349/o-1-space-java-solution

http://www.cs.princeton.edu/courses/archive/spring13/cos423/lectures.php

 

http://www.cs.princeton.edu/courses/archive/fall12/cos226/lectures.php

 

posted @ 2015-05-11 03:43  YRB  阅读(936)  评论(0编辑  收藏  举报