剑指offer——删除链表中重复的结点(好题!)

来源:互联网 发布:数据库常用sql语句 编辑:程序博客网 时间:2024/06/10 16:15

题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

思路:

需要删掉所有重复的节点。首先,题目已经告诉我们这是一个排序的链表,因此如果节点有重复,比如4,那么4的重复节点一定都排在一起。所以,可以通过遍历一次链表,就把所有重复节点删除。

不重复节点的特点,它和自己前后的节点都不一样。第一个满足这个条件的节点是新链表的头结点。


测试用例:
{1,1,1,1,1,1,2}
对应输出应该为:
{2}
你的输出为:
{}

没有考虑最后一个节点的特殊情况。

public class Solution {    public ListNode deleteDuplication(ListNode pHead)    {        if(pHead==null) // 链表是空            return null;        if(pHead.next==null) // 链表只有一个节点            return pHead;        boolean Head = false; //是否找到了新的头结点        ListNode newHead = null; // 新的头结点        ListNode temp = null; // 新链表的最后一个节点        if(pHead.next.val!=pHead.val){ // 原头结点即为新头结点的情况,分开考虑比较简洁            Head = true;            newHead = pHead;            temp = pHead;        }        ListNode pBefore = pHead;        ListNode pNow = pHead.next;        ListNode pNext = pHead.next.next;        while(pNext!=null){            if(pNow.val!=pBefore.val&&pNow.val!=pNext.val){                if(Head==false){                    Head = true;                    newHead = pNow;                    temp = pNow;                }                else{                    temp.next = pNow;                    temp = pNow;                }            }            pBefore = pNow;            pNow = pNext;            pNext = pNow.next;        }        if(temp!=null&&pNow.val!=temp.val&&pNow.val!=pBefore.val){ // 考虑最后一个节点            temp.next = pNow;            temp = pNow;        }        else if(temp==null&&pBefore.val!=pNow.val) // 除了最后一个节点,其他节点都重复的情况            newHead = pNow;        if(temp!=null){            temp.next = null; // 最后把temp(即新链表最后一个节点)的next设置为null        }        return newHead;    }}

另一种解法(头结点的设置技巧,判断不重复节点的技巧)

public class Solution {    public ListNode deleteDuplication(ListNode pHead)    {        ListNode first = new ListNode(-1);//设置一个trick        first.next = pHead; // 先令first.next = PHead ,针对PHead是null或者链表只有一个节点的情况,也可以返回正确值        //新建一个头节点解决了头节点就是重复值的麻烦!        ListNode p = pHead;        ListNode last = first; // 新链表的最后一个节点        while (p != null && p.next != null) {            if (p.val == p.next.val) { // 如果p的val和它下一个节点的val相等,说明这一定是一个重复节点                int val = p.val;                while (p!= null&&p.val == val)                    p = p.next;   // 把所有的重复节点都找出来                last.next = p; // 将last的下个节点设为p(但此时不更新last,因为有可能这个p也是重复的,要再经过一轮判断才能确定)            } else {                last = p; // 说明p既不和它前面的值相等,也不和后面的值相等,所以可以确定p在新链表中                p = p.next;            }        }        return first.next;    }    }

同样是设置头结点(自己写的,逻辑稍微清楚一些)

    public ListNode deleteDuplication(ListNode pHead)    {        ListNode fake = new ListNode(0);        ListNode temp = fake;        while(pHead!=null){            if(pHead.next!=null&&pHead.next.val==pHead.val){ //前面的一个判断是必要的,防止后面求val出现空指针异常                int flag = pHead.val;                while(pHead!=null&&pHead.val==flag)                    pHead = pHead.next;            }            else{                temp.next = pHead;                temp = temp.next;                pHead = pHead.next;            }        }        temp.next = null; // 这一步必不可少,譬如12355的情况,判断完55后直接跳出了,3节点的next节点没有被设置        return fake.next;    }

递归

public class Solution {    public ListNode deleteDuplication_1(ListNode pHead) {          // 递归停止条件          if (pHead == null || pHead.next == null)              return pHead;          ListNode current = pHead.next;          // 如果pHead是重复元素          if (pHead.val == current.val) {              current = current.next;              while (current != null && current.val == pHead.val)                  current = current.next;              pHead = current;              return deleteDuplication_1(current);          } else {              // pHead不是重复元素              pHead.next = deleteDuplication_1(current);              return pHead;          }  };
原创粉丝点击