(微软面试100题)判断两个链表是否相交

问题描述:

给定两个链表LinkList1, LinkList2, 判断两个链表是否相交?

解题思路:

这是一道常考题了,解题的思路主要如下:

1.首先要考虑到链表是否有环?

2. 如果链表没有环,则可以分别遍历链表,如果相交,最后两个指针一定会相遇

3. 如果有环且相交, 那么环上面的任意一个节点都一定会出现在另一个链表上。那么就变成了判断

    环上的点是否链表上的问题。

关于判断链表是否有环的算法:

这个算法应该在网上出现了很多次了。用两个指针同时指向链表头,一个指针的步长为1,另一个指针的步长为2,如果最后相遇,则证明有环。

否则链表无环。

为什么另一个指针的步长是2,就能一定保证在链表有环的情况下两个指针最后一定会相遇呢?有没有可能最后两个指针不相遇呢?

分析一下: 

       假设链表是有环的,我们称步长为2的指针为快指针(p_fast), 步长为1的指针为慢指针(p_slow).

       p_fast一定会先进入环,p_slow后进入环。假设当p_slow进入环时,p_fast到p_slow这间超出的节点个数为K. (p_fast有可能已经在环内转了几圈)

       如果N步之后, p_fast经过了2*N个节点, p_slow经过了N个节点

      要使它们能相遇:

       2*N = N + K

       N = K

      K为整数,N可以满足。所以一定会相遇。

      如果p_fast的步长为3呢?

      3*N = N + K

      2*N = K

      N = K/2

      此时如果K是奇数,那么p_fast和p_slow就永远没有相遇的一天了。

      所以快指针的步长为2不是随意定的。

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

typedef struct _node_t{
    int val;
    _node_t *next;
}node_t;

int check_loop(node_t *link_head, node_t **cross_node)
{
    node_t *p_fast;
    node_t *p_slow;
    int has_loop;

    p_fast   = link_head;
    p_slow   = link_head;
    has_loop = 0;

    while (p_fast != NULL && p_slow != NULL)
    {
        p_slow = p_slow->next;
        if (p_fast->next != NULL){
            p_fast = p_fast->next->next;
        }
        else {
            break;
        }
        if (p_slow == p_fast){
            has_loop = 1;
            *cross_node = p_slow;
            break;
        }
    }
    return has_loop;
}

int check_node_exist(node_t *link_head, node_t *node)
{
    node_t *p = link_head;
    int ret = 0;

    while (p)
    {
        if (p == node){
            ret = 1;
            break;
        }
        p = p->next;
    }
    return ret;
}

int link_cross(node_t *link_head1, node_t *link_head2)
{
    int flag1, flag2;
    int ret;
    node_t *node;

    flag1 = check_loop(link_head1, &node);
    flag2 = check_loop(link_head2, &node);
    ret   = 0;

    /* Neigher of the two link_list has loop */
    if (flag1 == 0 && flag2 == 0)
    {
        node_t *p1 = link_head1;
        node_t *p2 = link_head2;
        while (1)
        {
            if (p1 == p2){
                /* crossed */
                ret = 1;
                break;
            }
            if (p1->next){
                p1 = p1->next;
            }
            if (p2->next){
                p2 = p2->next;
            }
            if (p1->next == NULL && p2->next == NULL){
                /* both link_list come to the end */
                ret = 0;
                break;
            }
        }
    }
    else if (flag1 == 1){
        /* find out one node in the loop and check its existence in the other link_list*/
        ret = check_node_exist(link_head2, node);
    }
    else{
        /* find out one node in the loop and check its existence in the other link_list*/
        ret = check_node_exist(link_head1, node);
    }
    return ret;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值