Leetcode 链表 II 问题 142.错误的解决方案,但它为什么有效?

Leetcode Linked List II question No. 142.Wrong Solution but why does it work?

提问人:Rakshit Jain 提问时间:10/3/2023 更新时间:10/3/2023 访问量:67

问:

这是我用 leetcode 编写的代码,我知道它的实现是错误的,但为什么会这样呢?


struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *cur = head;

    while(cur){
        if(cur >= cur->next) return cur->next;
        
        cur = cur->next;
    }
    return NULL;
}

这段代码不应该工作,对吧?这应该是理想的解决方案

struct ListNode *fastp = head , *slowp = head;
        if(head == NULL || head->next == NULL)
            return NULL;

        struct ListNode *slow = head;
        struct ListNode *fast = head;
        struct ListNode *entry = head;

        while(fast->next && fast->next->next){
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast){ 
                while(slow != entry){
                    slow = slow->next;
                    entry = entry->next;
                }
                return entry;
            }
        }
        return NULL;
    }

换句话说,它总是可以表示为为什么所有节点的地址总是比以前少?

c malloc 单链接列表

评论

3赞 Retired Ninja 10/3/2023
你很幸运。不是一个可以指望的行为。
1赞 Chris 10/3/2023
也许节点已分配为数组,然后链接在一起。我以前在学术/竞赛环境中看到过这样做。
0赞 Shawn 10/3/2023
如果它通过了所有测试用例,真的错了吗?
3赞 Barmar 10/3/2023
@Shawn 如果此代码通过了所有测试用例,则问题出在测试用例上。
1赞 Barmar 10/3/2023
事实上。这真的是“为什么 leetcode 验证器会传递这个明显损坏的代码?这真的不是一个好的 SO 问题。

答:

1赞 trincot 10/3/2023 #1

错误代码假定不同节点的内存地址随着列表的遍历而增加。依赖列表中分配的节点的地址当然是错误的。如果所有测试用例都通过,这意味着测试用例以允许此逻辑给出正确答案的方式分配内存。例如,如果节点的分配顺序与添加到列表中的顺序相同,则连续节点的内存地址增加的可能性要大得多,而不是情况并非如此。

下面是一个测试用例,它可能会用错误的代码产生错误的结果:它创建一个链表 1→2→3→4→5→2(其中只有一个值为 2 的节点)。但节点的分配以不同的顺序进行,节点 2 最后分配。

假设调用了错误的函数并调用了正确的实现,然后尝试运行上述测试用例:detectCycleWrongdetectCycleCorrect

    struct ListNode *one = createNode(1);
    struct ListNode *three = createNode(3);
    struct ListNode *four = createNode(4);
    struct ListNode *five = createNode(5);
    // Allocated last: the node that will close the cycle
    struct ListNode *two = createNode(2);
 
    one->next = two;
    two->next = three;
    three->next = four;
    four->next = five;
    five->next = two;  // Back link
    
    struct ListNode *resultCorrect = detectCycleCorrect(one);
    printf("cycle at: %d\n", resultCorrect ? resultCorrect->val : -1);  // 2
    
    struct ListNode *resultWrong = detectCycleWrong(one);
    printf("cycle at: %d\n", resultWrong ? resultWrong->val : -1);  // 3?

正确的实现将输出 2,但错误的实现很可能(但不能保证)输出 3。

评论

0赞 Barmar 10/3/2023
您可以通过创建一个节点数组,然后排列其指针以指向特定索引来保证特定结果。next
0赞 Chris 10/3/2023
没有什么比链表更能说明“在现实世界中无用”了,链表将所有节点按顺序排列在一个数组中。