Floyd 判圈 算法

转自 leetcode 202------判断开心数

给定任意正数,比如19。

计算该正数各位上的数字的平方和,即12 + 92 = 82

重复第二步,对计算结果进行计算,得到

  • 82 + 22 = 68
  • 62 + 82 = 100
  • 12 + 02 + 02 = 1如果最后能够得到1,则认为是开心数。


    总结:

    1、

    int digitSquareSum(int n) {
        int sum = 0, tmp;
        while (n) {
            tmp = n % 10;
            sum += tmp * tmp;
            n /= 10;
        }
        return sum;
    }
    
    bool 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 1;
        else return 0;
    }

    这是一个单向链表问题,使用Floyd判圈算法,可以计算出其中有没有环。

    链接:http://blog.csdn.net/javasus/article/details/50015687

    http://www.siafoo.net/algorithm/10

    2、基础证明

    • 为什么会成环
      • for nin [1,10), g(n)>=n, since g(n)=n*n>=nwith equality hold onlyfor n=1
      • for other n with only highest digit nonzero (eg. 10, 90, 500, 4000,20000, etc), g(n)<n
      • and we can factor n into sum of numbers with only highest digitnonzero, eg. 12045 = 10000 + 2000 + 40 + 5

      in this way, we can show for any n>=100, g(n) < n
      对于任意正数n,跳转结果是有限的


    • 环的大小
      input: n (positive integer)
      func g = digitSquareSum
      while n>99
          n = g(n)
      output: HappyTable(n)
      可以计算[1,100]里面的所有情况,从而得到环的大小,以及这100个数的对应是否是开心数的表。

    • 使用表或者数组存储每步的计算结果和判断结果
      The common choice is to use map or set to check if there is a loop. since the maximum sum is no greater than 2x2 + 9x9x9 (2,999,999,999), we can use a 1000 lengh hashtable . It's not O(1) space but it's faster than the fast-slow pointer solution.

      class Solution {
      public:
          int tran(int n){
              int ans = 0;
              while(n){
                  ans += pow(n%10, 2);
                  n/=10;
              }
              return ans;
          }
          bool isHappy(int n) {
              bool rep[1000];
              memset(rep, 0, sizeof(rep));
              n = tran(n);
              while(!rep[n]){
                  rep[n] = true;
                  if(n == 1)
                      return true;   
                  n = tran(n);
              }
              return false;
          }
      };
      
      

    • 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;
      
      }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值