循环检测算法(哈希,双指针)
创始人
2024-01-25 11:15:09

文章目录

  • 快乐数
  • 环形链表
  • 环形链表II

快乐数

寻找快乐数

编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

各位数字上的平方之和再相加,最后如果得到了数字1,则这个数字就是快乐数,否则就不是。

快乐数具有以下的特性:

  • 数字满足条件,每位的数字平方后相加,最后的结果是1
  • 最后结果无法等于1,会进入循环。

数字有没有可能会无限大且没有循环?
答: 不可能。
例如数字: 2147483648,把他每一位拆分计算后:它肯定就会变成一个三位的数字,因此它不可能无限大下去,它一定会有一个循环或者最后结果为1.


方法一:
利用 哈希集和 统计计算的每一次的结果,如果陷入了循环,则哈希集合将显示为已经存在,因此此时就可以退出循环,即最后的结果为false;如果结果为1,则结束循环,返回true。

class Solution {
public:int getnum(int n){int sum=0;while (n){sum+=(n%10) * (n%10);n/=10;}return sum;}bool isHappy(int n) {unordered_set s;while (n!=1 && !s.count(n)){s.insert(n);n=getnum(n);}return n==1;}
};

方法二:
利用快慢指针,又叫龟兔赛跑法。

在这里插入图片描述

  • 一个快指针,一个慢指针。
  • 快指针每次走两步,慢指针一次走一步,当他们最后陷入循环的时候,快指针总是能追上慢指针。
  • 快指针自开始后必须每次都快于慢指针两步
  • 快指针为1,则结果为1,返回true
  • 快指针如果进入了循环,则它一定会等于慢指针,因此当他们相等的时候,循环结束,返回false。
class Solution {
public:int getnum(int n){int sum=0;while (n){sum+=(n%10) * (n%10);n/=10;}return sum;}bool isHappy(int n) {int slow=n;int fast=getnum(n);while (fast!=1 && fast!=slow){slow=getnum(slow);fast=getnum(getnum(fast));}return fast==1;}
};

环形链表

环形链表

给你一个链表的头节点 head ,判断链表中是否有环。
在这里插入图片描述
对于循环链表,我们也采用这种循环检测的算法,即双指针或者哈希集合的方式:

首先来哈希集和:

  • 利用哈希集合来存储每一个节点,如果在之后遍历到的节点的存在于哈希集合中,则结束循环,此链表是环形的。
  • 如果一直遍历到了空节点,则不是环形的。
class Solution {
public:bool hasCycle(ListNode *head) {unordered_set s;ListNode* p=head;while (p!=nullptr && !s.count(p)){s.insert(p);p=p->next;}return p!=nullptr;}
};

方法二:
快慢指针法:

  • 快指针每次走两步,慢指针每次走一步,快指针必须领先于慢指针两步。
  • 快指针在某时刻碰见了慢指针,则是环形的,否则如果快指针到了nullptr,则不是环形的。
class Solution {
public:bool hasCycle(ListNode *head) {if (!head || !head->next){return false;}ListNode* pfast=head->next;ListNode* pslow=head;while (pfast!=nullptr && pfast!=pslow){pslow=pslow->next;pfast=pfast->next;if (pfast!=nullptr){pfast=pfast->next;}}return pfast!=nullptr;}
};

环形链表II

我们利用双指针或者哈希集合能够很轻松的检测到是否有循环发生,以及何时退出循环,但是我们该如何返回刚进入循环时的第一个节点呢?

使用哈希集和可以很轻松的解决这个问题

  • 哈希集和存储每一个节点
  • 遍历到了已存在于哈希集和中的节点,则它就是循环的入口节点,直接返回就好

我们如果使用双指针,该如何获得链表得入口节点呢??

这还不简单,当快指针等于慢指针得时候,定义一个临时得节点,然后让他走到快指针的位置,返回这个位置,不就是这个入口节点吗?

大家仔细想一想,快慢指针的相遇不一定是在入口节点发生的,有可能在循环的圈内,因此返回快指针的位置是完全错误的。。

我们首先来整理一下思路:
在这里插入图片描述

  • 假设快指针和慢指针在图中圈内的紫色位置相遇。
  • 快指针走过的路程:a + n (b + c) + b
  • 任意时刻,快指针走的路程一定是慢指针的两倍,快指针走的路程: 2(a + b)
  • 因此: a + n (b + c) + b = 2(a + b)
  • 得到距离公式:a=c+(n−1)(b+c)

a=c+(n−1)(b+ c 这个公式是什么意思??
我们把它翻译成人话:

从相遇点到入环点的距离加上 n−1 圈的环长,恰好等于从链表头部到入环点的距离。

因此当一个临时指针和慢指针同时每次走一步,slow从相遇点开始走,pTemp从链表头开始走,最后他们会同时在入口节点处相遇:

class Solution {
public:ListNode *detectCycle(ListNode *head) {ListNode* pfast=head;ListNode* pslow=head;while (pfast!=nullptr){pslow=pslow->next;if (pfast->next==nullptr){return nullptr;}pfast=pfast->next->next;if (pfast==pslow){ListNode* pTemp=head;while (pTemp!=pslow){pTemp=pTemp->next;pslow=pslow->next;}return pTemp;}}return nullptr;}
};

相关内容

热门资讯

什么是419 419是什么意思... 嗨,辣条陪你理智吃瓜最近刚还想着10月特殊时期可能没啥瓜了,结果一到月底就来了。孟美岐冷不丁就突然上...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
什么是419 419是什么意思... 嗨,辣条陪你理智吃瓜最近刚还想着10月特殊时期可能没啥瓜了,结果一到月底就来了。孟美岐冷不丁就突然上...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...