查找循环链表(leetcode 141)

原题是Leetcode https://leetcode.com/problems/linked-list-cycle/

判断下图中的链表是否有循环

一开始我的想法很简单,做一个循环,然后把之前遇到过的地址放在一个数组中,遇到新的地址就和之前的数组比对,看是否存在,如果存在,则返回true。

代码很简单,很快就能写好。

bool hasCycle(struct ListNode *head) {
    char * tab[10000];
    int size = 0; 
    while(head)
    {
        tab[size++] = head;
        head = head->next;
        for(int i = 0; i < size; i++)
            if(head == tab[i])
                return true;
    }
    return false;
}

能够通过但是成绩却很差,时间复杂度基本上是O(N2)。看了网上一些思路,其实还有更高效两种解法。

1 步长

bool hasCycle(struct ListNode *head) {
    if (head == NULL || head->next == NULL) {
        return false;
    }

    struct ListNode *slow = head;
    struct ListNode *fast = head->next;

    while (fast != NULL && fast->next != NULL) {
        if (slow == fast) {
            return true; // Cycle detected
        }

        slow = slow->next;
        fast = fast->next->next;
    }

    return false; // No cycle found
}

一开始不好理解,但是如果把链表看成是一个圈,那么快指针没多久就会转回来,最后和慢指针重合,从而检测到闭环。

2 检测内存位置:

​​​​bool hasCycle(struct ListNode *head) {
    while(head != NULL && head->next != NULL)
    {
        if(head->next <= head)
            return true;
        head = head->next;
    }

    return false; // No cycle found
}

从代码简洁测度,这个几乎是最简单的一版了。效率也很好。就是判断新的节点地址是否小于之前节点,如果是,则存在闭环。

有点好奇这个方案,我也写了一个程序验证地址的问题。

    int *p1 = malloc(sizeof(int));
    printf("%p\n", p1);
    p1 = malloc(sizeof(int));
    printf("%p\n", p1);
    p1 = malloc(sizeof(int));
    printf("%p\n", p1);
    p1 = malloc(sizeof(int));
    printf("%p\n", p1);
    p1 = malloc(sizeof(int));
    printf("%p\n", p1);
    p1 = malloc(sizeof(int));
    printf("%p\n", p1);
    p1 = malloc(sizeof(int));
    printf("%p\n", p1);
    p1 = malloc(sizeof(int));
    printf("%p\n", p1);
    p1 = malloc(sizeof(int));
    printf("%p\n", p1);

输出确实是依次增加4字节:

0X00A02028
0X00A02038
0X00A02048
0X00A02058
0X00A02068
0X00A02078
0X00A02088

借网上大神的一张图,malloc是分配在下面蓝色的部分,从下往上。

百度安全验证

leetcode的初始链表应该是使用malloc。malloc的内存是在堆上分配,从下往上,如果新的malloc内容,一般来说地址都在更高位。所以第二种方法是根据这种特性来判断的。

但是呢。。。个人觉得这种方法还是太投机了,leetcode这边是按照顺序分配,但是谁能保证其它情况后面的节点就一定是后分配内存呢?我先分配了后面再用难道不行?所以还是第一种方法为佳。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值