首页 > 其他分享 >快乐数-快慢指针法

快乐数-快慢指针法

时间:2024-07-25 17:28:09浏览次数:16  
标签:getNext 快慢 int 链表 fastRunner 快乐 慢跑 指针

题目描述:

个人题解:

通过反复调用 getNext(n) 得到的链是一个隐式的链表。隐式意味着我们没有实际的链表节点和指针,但数据仍然形成链表结构。起始数字是链表的头 “节点”,链中的所有其他数字都是节点。next 指针是通过调用 getNext(n) 函数获得。

意识到我们实际有个链表,那么这个问题就可以转换为检测一个链表是否有环。因此我们在这里可以使用弗洛伊德循环查找算法。这个算法是两个奔跑选手,一个跑的快,一个跑得慢。在龟兔赛跑的寓言中,跑的慢的称为 “乌龟”,跑得快的称为 “兔子”。

不管乌龟和兔子在循环中从哪里开始,它们最终都会相遇。这是因为兔子每走一步就向乌龟靠近一个节点(在它们的移动方向上)。

我们不是只跟踪链表中的一个值,而是跟踪两个值,称为快跑者和慢跑者。在算法的每一步中,慢速在链表中前进 1 个节点,快跑者前进 2 个节点(对 getNext(n) 函数的嵌套调用)。

如果 n 是一个快乐数,即没有循环,那么快跑者最终会比慢跑者先到达数字 1。

如果 n 不是一个快乐的数字,那么最终快跑者和慢跑者将在同一个数字上相遇。

代码实现:

class Solution {
    public int getNext(int n) {
        int totalSum = 0;
        while (n > 0) {
            int d = n % 10;
            n = n / 10;
            totalSum += d * d;
        }
        return totalSum;
    }

    public bool IsHappy(int n) {
        int slowRunner = n;
        int fastRunner = getNext(n);
        while (fastRunner != 1 && slowRunner != fastRunner) {
            slowRunner = getNext(slowRunner);
            fastRunner = getNext(getNext(fastRunner));
        }
        return fastRunner == 1;
    }
}

复杂度分析:

时间复杂度:O(logn)

        该分析建立在对前一种方法的分析的基础上,但是这次我们需要跟踪两个指针而不是一个指针来分析,以及在它们相遇前需要绕着这个循环走多少次。
如果没有循环,那么快跑者将先到达 1,慢跑者将到达链表中的一半。我们知道最坏的情况下,成本是 O(2⋅logn)=O(logn)。一旦两个指针都在循环中,在每个循环中,快跑者将离慢跑者更近一步。一旦快跑者落后慢跑者一步,他们就会在下一步相遇。假设循环中有 k 个数字。如果他们的起点是相隔 k−1 的位置(这是他们可以开始的最远的距离),那么快跑者需要 k−1 步才能到达慢跑者,这对于我们的目的来说也是不变的。因此,主操作仍然在计算起始 n 的下一个值,即O(logn)。
空间复杂度:O(1)

        对于这种方法,我们不需要哈希集来检测循环。指针需要常数的额外空间。

标签:getNext,快慢,int,链表,fastRunner,快乐,慢跑,指针
From: https://blog.csdn.net/qq_45031559/article/details/140646954

相关文章

  • 指针的用法
    大家好,这次是用法系列第二期,给大家介绍指针的作用。一.用于变量我举个例子#include<iostream>usingnamespacestd;intmain(){ intx=6,y=5;//创建变量x,y int*p=&x;//创建指针p并指向x cout<<*p<<endl;//输出指针p *p=y;//指针指向y cout<<*p;//输出指针p......
  • 【C】指针
    目录定义声明指针地址运算符和取值运算符初始化指针使用指针指针的算术操作空指针和野指针指针与数组指针运算指针与整数的加减指针间的减法指针比较在C语言中,指针是一个非常重要的概念,它直接关联到内存管理和数据访问的效率。定义指针是内存中一个最小单元......
  • 翻转字符串里的单词(双指针去重思路+代码实现)
    题目①双指针思路整体思路:去重+反转数组填充类问题都可以使用双指针方式!原理如同:双指针移除元素去重其实是一种删除操作,1.双指针去重fast判断slow指向待填充位置额外再使用一个变量:isblock(判断之前是否出现过空格)连续空格的话只保留一个空格,达到去重效果遇......
  • 力扣:三数之和(左右双指针思路+动画演示+代码实现)
    题目①双指针思路(双指针匹配方式,还不涉及去重)1.需要的变量个数(三个变量,双指针作为其中两个)left、right已经两个变量,表示两个数。题目求三数之和,只需要另外一个变量i即可!所以一共是nums[i]、nums[left]、nums[right]。存储满足条件的这三个值2.双指针工作原理......
  • C语言:指针1(详细讲解)
     目录指针变量和地址取地址操作符指针变量的大小指针变量类型意义指针解引⽤指针的+-整数const修饰指针const修饰变量const修饰指针变量指针的运算指针+-整数 指针的关系运算野指针指针未初始化 指针越界访问指针指向的空间被释放了避免野指针assert......
  • c++11(3): 类型推导与智能指针
    41.两个右尖括号>在模板中不再被判定为右移,需要右移需要加圆括号()42.auto类型推导,编译时推导inta=1;autob=a;//b的类型为int1):auto不能作函数形参类型2):auto不能对结构体中的肥静态成员进行推导3):auto不能声明数组4):auto不能在实例化模板时作为......
  • C语言 ——— 函数指针数组的讲解及其用法
    目录前言函数指针数组的定义函数指针数组的使用前言数组是存放一组相同类型数据的存储空间关于指针数组的知识请见:C语言———指针数组&指针数组模拟二维整型数组-CSDN博客那么要将多个函数的地址存储到数组中,这个数组该如何定义呢?函数指针数组的定义把多个函数......
  • 深入理解指针(2)
    一、数组名的理解首先我们先做一个测试:#include"stdio.h"intmain(){ intarr[10]={1,2,3,4,5,6,7,8,9,10}; printf("&arr[0]=%p\n",&arr[0]); printf("arr=%p\n",arr); return0;}输出结果:我们发现数组名和数组首元素的地址打印出的结果一模一样,数组名......
  • 深入理解指针(3)
    一、字符指针变量字符指针变量一般用char*来表示一般使用:#include"stdio.h"intmain(){charch='w';char*pc=&ch;*pc='w';return0;}还有一种使用方法:#include"stdio.h"intmain(){constchar*pc="hellobit......
  • C++this指针--指针的介绍用法以及相关注意事项
    什么是this指针this指针是在C++中用来指向当前对象的特殊指针。它是每个非静态成员函数的隐式参数,指向调用该函数的对象。在C++类的成员函数中,除了静态成员函数外,每个成员函数都有一个隐含的this指针,它指向调用该函数的对象。这个指针可以让成员函数访问调用它的对象......