gpt4 book ai didi

java - 从排序的链表中删除重复的节点。为什么我的输出错误?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:58:43 28 4
gpt4 key购买 nike

给定一个排序链表,删除所有具有重复数字的节点,只留下与原始列表不同的数字。

例子:

  • 给定 1->2->3->3->4->4->5->null,返回 1->2->5->空

  • 给定 1->1->1->2->3->null,返回 2->3->null

问题:

  • 给定 1->1->1->2->3->null,我下面的解决方案 return 3->null

谁能告诉我为什么?

/**
* Definition for ListNode
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
/**
* @param ListNode head is the head of the linked list
* @return: ListNode head of the linked list
*/
public static ListNode deleteDuplicates(ListNode head) {
// write your code here
if(head == null || head.next == null) return head;

ListNode post = head.next;
ListNode curr = head;
ListNode dummy = new ListNode(head.val-1); // make sure dummy node value is different from the head
dummy.next = head;
ListNode prev = dummy;

while(post != null) {
//System.out.println("prev.val = " + prev.val + ", curr.val = " + curr.val + ", post.val = " + post.val + ", prev.next.val = " + prev.next.val);
//System.out.println("prev.next.val = " + prev.next.val + ", curr.next.val = " + curr.next.val);

if(prev.next.val == curr.val && prev.next.val == post.val) {
curr = curr.next;
post = post.next;
}
else if(prev.next.val == curr.val && prev.next.val != post.val) {
curr = curr.next;
post = post.next;
prev.next = curr;
}
else {
prev = prev.next;
curr = curr.next;
post = post.next;
}
}

return dummy.next;
}
}

最佳答案

在不改变你的程序做什么的情况下,while 循环可以转换为这种更具可读性的形式:

while (post != null) {
if (prev.next.val != curr.val || prev.next.val != post.val) {
if (prev.next.val == curr.val) {
prev.next = curr.next;
} else {
prev = prev.next;
}
}
curr = curr.next;
post = post.next;
}

这等同于您的实际代码。我将基于此版本进行说明,因为我发现这更容易阅读和推理。

让我们观察一些事情:

  • 一开始,prev.next 指向curr。所以 prev.next.val 等于 curr.val。此外,postcurr 领先一步。

  • currpost 一起移动。currpostif 条件中没有改变,作为循环的最后一步,他们都前进了一个位置。

给定输入 1、1、1、2、3 和上述观察结果:

  • post 达到 2 之前,外部 if 条件将为假。

  • curr 落后一步,所以它指向 2 之前的 1。

  • prev没有动,所以prev.next还是指向第一个1。

  • 所以此时,prev.next.val等于curr.val(均为1),但它不等于 post.val,即 2。所以我们进入外层if。

  • 作为prev.next.val == curr.val,我们也进入了内部的if,并设置 prev.next = curr.next。请记住,循环的最后一步是将 curr 推进到 curr.next。所以 prev.next 将指向 curr

  • 在下一次迭代中,post 位于 3,curr 位于 2,prev.next 指向 当前。所以我们进入另一个if,然后是内部的if,设置prev.nextcurr.next,这是 3。

这就是结局。 prev 从未移动,它停留在原处,即 dummyprev.next 指向 3,我们错误地返回了它。请注意,如果输入较长,例如 1、1、1、2、3、4、5、6,同样的行为将继续,prev.nextcurr 之后,并且该实现会错误地返回 6 -> null。算法坏了。


考虑这个替代算法:

  1. 创建一个虚拟节点,指向下一个head(就像你已经做的那样)
  2. 设置当前节点为dummy
  3. 当下一个节点存在时,下一个-下一个节点存在
    • 比较 next.valnext.next.val
    • 如果不相等,则前进当前节点
    • 如果相等,则:
      • 保存一份 next.val
      • 跳过 nextnext.next(设置在 next.next.next 旁边)
      • 跳过所有值等于保存的 val
      • 的其他节点
  4. 返回dummy.next

像这样:

if (head == null) return head;

ListNode dummy = new ListNode(head.val - 1);
dummy.next = head;

ListNode node = dummy;
while (node.next != null && node.next.next != null) {
if (node.next.val != node.next.next.val) {
node = node.next;
} else {
int val = node.next.val;
node.next = node.next.next.next;
while (node.next != null && node.next.val == val) {
node.next = node.next.next;
}
}
}

return dummy.next;

关于java - 从排序的链表中删除重复的节点。为什么我的输出错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40617392/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com