【算法面试题】带环链表之灵魂三问!

带环链表之灵魂三问!

今天舍友二狗子又去面试了,回来就问我们算法问题,看来对于ios开发来说算法是一个大难题啊!
今天是什么呢?当然是带环链表的问题了。
这就让我想起了当初的带环链表三连问!现场慌的不行不行的。

一、判断链表是否有环

一句话解释:使用快慢指针,同时指向头节点,slow指针每次走一个节点,fast指针每次走两个节点,最终如果两个指针相遇,则表示有环!

二、找出环的入口

第一问很简单,第二问就有点难度了,哈哈!当初栽过跟头了,都是泪~
假设:快慢指针都从环的入口开始走,那么在慢指针跑一圈,快指针跑两圈的时候,两个指针肯定在入口处相遇;
那么:如果快慢指针从链表头开始走的话呢?当两个指针相遇的时候,就表示:快指针走的距离 = n个环的距离 + 慢指针走的距离环的长度=相遇点和入口两段的距离慢指针走的距离可以简化为:链表开头到环入口+环入口到相遇点的距离
结论:链表入口到环入口距离 = n个环的长度+慢指针到环入口距离,那么慢指针到环入口距离==链表入口到环入口距离,只要快指针指向链表入口,和慢指针同步移动,再次相遇的节点就是环的入口节点;(SUCCESS)

三、计算环的长度

这个是在第二步的基础上计算的,只要找到环的入口,走一遍就可以算出长度了!

四、代码实现

#include <stdio.h>
#include <stdlib.h>

struct Node{
    int num;
    struct Node *next;
};

void initList(struct Node *ListHead){
    struct Node *node1 = malloc(sizeof(struct Node));
    struct Node *node2 = malloc(sizeof(struct Node));
    struct Node *node3 = malloc(sizeof(struct Node));
    struct Node *node4 = malloc(sizeof(struct Node));
    struct Node *node5 = malloc(sizeof(struct Node));
    struct Node *node6 = malloc(sizeof(struct Node));
    struct Node *node7 = malloc(sizeof(struct Node));
    struct Node *node8 = malloc(sizeof(struct Node));
    struct Node *node9 = malloc(sizeof(struct Node));
    struct Node *node10 = malloc(sizeof(struct Node));
    struct Node *node11 = malloc(sizeof(struct Node));
    struct Node *node12 = malloc(sizeof(struct Node));

    ListHead->num = 0;
    node1->num = 1;
    node2->num = 2;
    node3->num = 3;
    node4->num = 4;
    node5->num = 5;
    node6->num = 6;
    node7->num = 7;
    node8->num = 8;
    node9->num = 9;
    node10->num = 10;
    node11->num = 11;
    node12->num = 12;

    ListHead->next = node1;
    node1->next = node2;
    node2->next = node3;
    node3->next = node4;
    node4->next = node5;
    node5->next = node6;
    node6->next = node7;
    node7->next = node8;
    node8->next = node9;
    node9->next = node10;
    node10->next = node11;
    node11->next = node12;
    node12->next = node4;

    printf("Set Address: %p, Value:%d \r\n", node4, node4->num);
}

int main(){
    struct Node *ListHead = malloc(sizeof(struct Node));

    // 0. 初始化链表
    initList(ListHead);

    // 1. 判断是否有环
    struct Node *slow = ListHead->next;
    struct Node *fast = ListHead->next->next;

    for(;;){
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast){
            printf("YES! slow=fast address: %p, Value: %d \r\n", slow, slow->num);
            break;
        }
    }

    // 2. 寻找环的入口
    fast = ListHead;
    for(;;){
        slow = slow->next;
        fast = fast->next;
        if(slow == fast) break;
    }
    printf("Enter Address: %p, Value: %d \r\n", slow, slow->num);

    // 3. 计算环的长度
    int i = 0;
    fast = slow->next;
    for(i=1; fast!=slow; i++)
        fast = fast->next;

    printf("Length: %d\r\n", i);

    return 0;
}

——2020-04-09——

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值