巧用快慢指针处理循环问题

循环类问题的一个解题思路为:设置一个慢指针,每次步进1,一个快指针,每次步进2,则快慢指针总会出现相遇的情况。比如一个数组[1,2,3,4],快指针和慢指针都从第一个元素开始遍历,如下图,第5趟后他们就相遇了

 下面来看今天在leetcode碰到的一道题:验证一个数是否为快乐数?

快乐数的定义如下:

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

我的第一印象就是使用一个数组来记录这个数是否验证过,如果是就存到数组中,后面再验证鑫生成的数的时候查一下数组是否存在,如果存在就不是快乐数,如果最后生成的数的每个位数平方和为1,则为快乐数,实现代码如下:

     /**
     * 通过数组检验方式
     */
    private boolean isHappyByList(int n){
        //初始化list存储每次校验的值
        List<Integer> existList = new ArrayList<>();
        //校验n是否为快乐数
        while(true){
            //n为1的时候,则为快乐数
            if(n == 1){
                return true;
            }
            //如果n为之前出现过的数,则不是快乐数
            if(existList.contains(n)){
                return false;
            }
            //将n标记为出现过的数存入list
            existList.add(n);
            //count记录n每个位数上的平方值总和
            int count =0;
            //计算n每个位数上的平方值总和
            while(n>0){
                int i = n%10;
                count += i*i;
                n /=10;
            }
            n = count;
        }
    }

后面看到评论有同学使用了快慢指针,仔细一想,这种数的计算就是一个循环问题,实现代码如下:

    /** 
     * 通过快慢指针方式
     * 设置一个慢指针每次计算一次,一个快指针每次计算两次
     * 快乐数最后两个指针结果都是1
     * 非快乐数会存在循环,则慢指针总会赶上快指针
     */
     private boolean isHappyByPoint(int n){
         int slow = n, fast = n;
         do {
             slow = dealNum(slow);
             fast = dealNum(fast);
             fast = dealNum(fast);
         } while (slow != fast);
         return slow == 1;
     }

    /**
     * 计算一个数每个位数上的数值的平方和
     */
     private int dealNum(int n){
         int count =0;
        //计算n每个位数上的平方值总和
        while(n>0){
            int i = n%10;
            count += i*i;
            n /=10;
        }
        return count;
     }

总结,遇到类似问题的时候,如果发现是循环问题,应该尝试从快慢指针的角度出发考虑,会有解题的惊喜!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值