在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表 1->2->3->3->4->4->5 处理后为 1->2->5
数据范围:链表长度满足 ,链表中的值满足
进阶:空间复杂度 ,时间复杂度
例如输入{1,2,3,3,4,4,5}时,对应的输出为{1,2,5},对应的输入输出链表如下图所示:
{1,2,3,3,4,4,5}
{1,2,5}
{1,1,1,8}
{8}
# -*- coding:utf-8 -*- ''' 题目:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 ''' class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: def deleteDuplication(self, pHead): # write code here if pHead == None or pHead.next == None: return pHead new_head = ListNode(-1) new_head.next = pHead pre = new_head p = pHead nex = None while p != None and p.next != None: nex = p.next if p.val == nex.val: while nex != None and nex.val == p.val: nex = nex.next pre.next = nex p = nex else: pre = p p = p.next return new_head.next
class Solution: def deleteDuplication(self, pHead): if not pHead or not pHead.next: return pHead if pHead.val == pHead.next.val: temp = pHead.next while temp and temp.val == pHead.val: temp = temp.next return self.deleteDuplication(temp) else: pHead.next = self.deleteDuplication(pHead.next) return pHead
public ListNode deleteDuplication(ListNode pHead){ if(pHead == null){ return null; } if(pHead.next == null){ return pHead; } //两个循环,用来应付“1-1-2-2-3-3-4-5…”格式的连续重复结点 while(pHead != null && pHead.next != null && pHead.val == pHead.next.val){ while(pHead != null && pHead.next != null && pHead.val == pHead.next.val){ pHead = pHead.next; } pHead = pHead.next; } if(pHead!=null ){ pHead.next = deleteDuplication(pHead.next); } return pHead; }
再新建一个链表返回即可。很暴力。
class Solution:
def deleteDuplication(self, pHead):
res = []
while pHead:
res.append(pHead.val)
pHead = pHead.next
res = list(filter(lambda c: res.count(c) == 1, res))
dummy = ListNode(0)
pre = dummy
for i in res:
node = ListNode(i)
pre.next = node
pre = pre.next
return dummy.next
/* *因为需要删除重复的节点,所以需要保留一个待删除节点之前的节点,这里用一个指针pre来 *表示,另外再用一个指针p指向正在遍历的节点。当头节点与后续节点数值相等时,需要特殊 *处理。方法比较简单,就是注意不要出现NULL->next,引起系统报错。 */ class Solution { public: ListNode* deleteDuplication(ListNode* pHead) { if (pHead == NULL) return NULL; ListNode *pre = NULL; ListNode *p = pHead; int flag = 0; //判断是否出现重复节点,当flag==1时,当前节点出现重复 while (p) { while (p->next && p->val == p->next->val) //如果节点重复,一直遍历下去 { flag = 1; p = p->next; } if (flag == 0) //如果当前节点不重复,遍历下一个节点 { pre = p; p = p->next; } else //如果当前节点重复,分类处理 { flag = 0; if (pre == NULL) //如果从头结点开始出现重复,重置头结点指针 { pHead = p->next; p = pHead; } else //否则,跳过重复的节点 { pre->next = p->next; p = pre->next; } } } return pHead; } };
public class Solution { public ListNode deleteDuplication(ListNode pHead) { if(pHead==null)return null; ListNode preNode = null; ListNode node = pHead; while(node!=null){ ListNode nextNode = node.next; boolean needDelete = false; if(nextNode!=null&&nextNode.val==node.val){ needDelete = true; } if(!needDelete){ preNode = node; node = node.next; } else{ int value = node.val; ListNode toBeDel = node; while(toBeDel!=null&&toBeDel.val == value){ nextNode = toBeDel.next; toBeDel = nextNode; if(preNode==null) pHead = nextNode; else preNode.next = nextNode; node = nextNode; } } } return pHead; } }
class Solution: def deleteDuplication(self, pHead): head = ListNode(None) head.next = pHead p = head q = pHead # 输入为空 if not q: return None # 循环整个链表 while q.next: # 当 q 不等于 r 时 if q.val != q.next.val: # p 与 q 不相连,说明有重复 if q != p.next: p.next = q.next # p 与 q 相连,不处理,继续移动 p else: p = q q = q.next # 判断链表结尾是重复的问题 if q != p.next: p.next = q.next return head.next
class Solution { public: ListNode* deleteDuplication(ListNode* pHead) { ListNode* p=pHead; if(!p||!p->next) return pHead; ListNode* pre=NULL; bool check = false; while(p){ while(p->next&&p->val==p->next->val){ p = p->next; check = true; } if(check){ if(pre) pre->next = p->next; else pHead = p->next; check = false; } else{ pre = p; } if(p){ p = p->next; } } return pHead; } };
//Java版递归 public ListNode deleteDuplication(ListNode pHead) { if (pHead == null) return null; if (pHead.next == null) return pHead; ListNode cur; //对重复结点的处理 if (pHead.val == pHead.next.val) { cur = pHead.next.next; //遍历到没有重复结点的位置 while (cur != null && cur.val == pHead.val) { cur = cur.next; } return deleteDuplication(cur); } //该结点不重复,递归下一个结点 cur = pHead.next; pHead.next = deleteDuplication(cur); return pHead; }
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } }; */ class Solution { public: ListNode* deleteDuplication(ListNode* pHead) { if(pHead==0) return 0; map<int,int> m; ListNode* p=pHead; while(p!=0) { m[p->val]++; p=p->next; } //判断head while(m[pHead->val]>1) { pHead=pHead->next; if(pHead==0) return 0; } ListNode* p1=pHead; ListNode* p2=pHead->next; while(p2!=0) { if(m[p2->val]>1) { p2=p2->next; p1->next=p2; } else { p2=p2->next; p1=p1->next; } } return pHead; } };
/* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } */ import java.util.HashMap; public class Solution { public ListNode deleteDuplication(ListNode pHead) { if(pHead==null || pHead.next==null) return pHead; ListNode list=new ListNode(-1); ListNode demo=list; ListNode p=pHead; ListNode q=null; while(p!=null){ int value=p.val; q=p; if((q.next!=null) && (value==q.next.val)){ while((q.next!=null)&&(value==q.next.val)){ q=q.next; } p=q.next; }else{ ListNode newnode=new ListNode(p.val); demo.next=newnode; demo=demo.next; p=p.next; } } return list.next; } }
typedef ListNode node; typedef node* pode; class Solution { public: ListNode* deleteDuplication(ListNode* p){ node h(0x23333), *q = &h, *tmp; int cnt; while(p){ tmp = p; p = p -> next; cnt = 0; while(p && p -> val == tmp -> val) p = p -> next, ++cnt; if(!cnt) q -> next = tmp, q = tmp; } q -> next = NULL; return h.next; } };
typedef ListNode node; typedef node* pode; class Solution { public: ListNode* deleteDuplication(ListNode* p){ node h(0x23333), *q = &h; while(p){ while(p && p -> next && p -> next -> val == p -> val){ while(p -> next && p -> next -> val == p -> val) p = p -> next; p = p -> next; } if(!p) break; q -> next = p; q = p; p = p -> next; } q -> next = NULL; return h.next; } };
/* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } */ /* 算法思想:方法一,递归实现。 public class Solution { public ListNode deleteDuplication(ListNode pHead) { if(pHead == null || pHead.next == null) return pHead; if(pHead.val != pHead.next.val){ pHead.next = deleteDuplication(pHead.next); return pHead; }else{ int val = pHead.val; while(pHead.val == val){ pHead = pHead.next; if(pHead == null) return null; } return deleteDuplication(pHead); } } } */ /* 算法思想:把当前结点的前一个结点(pre)和后面值比当前结点的值要大的结点相连。 */ public class Solution { public ListNode deleteDuplication(ListNode pHead) { if(pHead == null || pHead.next == null) return pHead; ListNode temp = new ListNode(-1); temp.next = pHead; ListNode curNode = pHead; ListNode pre = temp; while(curNode != null && curNode.next != null){ ListNode next = curNode.next; if(curNode.val == next.val){ while(next != null && curNode.val == next.val){ next = next.next; } pre.next = next; curNode = next; }else{ pre = curNode; curNode = curNode.next; } } return temp.next; } }
没什么复杂绕圈的,主要还是考验逻辑和代码能力。
刚开始想在if (pHead.next != null && pHead.val == pHead.next.val)里套一个同样内容的while,但强迫症犯了看到重复部分很不爽,花了点时间写成如下形式,看起来简洁一些,我是看着挺舒服的。
说明:
如果当前结点和下一个重复,则pre.next设空,否则,如果pre.next为空,则跳过当前结点(代表当前结点为同类重复结点的最后一个).
public ListNode deleteDuplication(ListNode pHead) { ListNode h = new ListNode(0), p = h; h.next = pHead; while (pHead != null) { if (pHead.next != null && pHead.val == pHead.next.val) { p.next = null; } else if (pHead.next != null && p.next == null) { p.next = pHead.next; } else { p = p.next; } pHead = pHead.next; } return h.next; }
public ListNode deleteDuplication(ListNode pHead) { if(pHead==null||pHead.next==null) return pHead; else { //新建一个节点,防止头结点要被删除 ListNode newHead=new ListNode(-1); newHead.next=pHead; ListNode pre=newHead; ListNode p=pHead; ListNode next=null; while(p!=null && p.next!=null) { next=p.next; if(p.val==next.val)//如果当前节点的值和下一个节点的值相等 { while(next!=null && next.val==p.val)//向后重复查找 next=next.next; pre.next=next;//指针赋值,就相当于删除 p=next; } else{ //如果当前节点和下一个节点值不等,则向后移动一位 pre=p; p=p.next; } } return newHead.next;//返回头结点的下一个节点 } }
# 思路简单版,为了便于处理头节点,手动增加虚拟首结点,分别设置4个指针 # anchor:标志链接位置,初始化为虚拟首结点 # former:标志待判断节点的直接前驱,初始化为虚拟首结点 # x:标志待判断节点本身,初始化为头节点 # latter:标志待判断节点的直接后继,初始化为头节点后继 # 根据题意,只有某节点与其直接前驱和直接后继都不相同时,才保留 # latter到链表结尾,或者整个链表为空时为退化情况 def deleteDuplication(self, pHead): # write code here if not pHead: # 如果链表为空 return None Head = ListNode(None) # 虚拟首结点 Head.next = pHead anchor, former, x, latter = Head, Head, Head.next, Head.next.next # 初始化 while(latter): # 当遍历节点都不是空(都有值)的时候 if former.val != x.val and x.val != latter.val: # 如果x为一个不重复的节点,则链入返回的链上 anchor.next = x anchor = anchor.next former, x, latter = x, latter, latter.next # 指针向后移动 if former.val == x.val: # 最后一个节点,如果重复就不要,否则要 anchor.next = None else: anchor.next = x return Head.next # 去掉虚拟首结点,返回
/* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } */ public class Solution { public ListNode deleteDuplication(ListNode pHead) { ListNode newHead = new ListNode(-1); newHead.next = pHead; ListNode pre = newHead; ListNode node = pHead; while(node!=null&&node.next!=null){ if(node.val==node.next.val){ while(node!=null&&node.next!=null&&node.val==node.next.val){ node = node.next; } pre.next = node.next; node = node.next; } else{ pre = node; node = node.next; } } return newHead.next; } }
public ListNode deleteDuplication(ListNode pHead){ ListNode first = new ListNode(Integer.MIN_VALUE),last; first.next = pHead; last = first; while (pHead != null && pHead.next != null) { if (pHead.val == pHead.next.val) { int val = pHead.val; while (pHead!= null && pHead.val == val) pHead = pHead.next; last.next = pHead; } else { last = pHead; pHead = pHead.next; } } return first.next; }
// public ListNode deleteDuplication(ListNode pHead){ // LinkedList<ListNode> result = new LinkedList<ListNode>(); // result.addLast(new ListNode(Integer.MIN_VALUE)); // boolean isRepeated = false; // while (pHead != null){ // if (result.getLast().val == pHead.val){ // isRepeated = true; // } // else { // if (isRepeated){ // result.removeLast(); // isRepeated = false; // } // result.addLast(pHead); // } // pHead = pHead.next; // } // if (isRepeated) result.removeLast(); // // if (result.size() == 1) return null; // // for (int i = 0; i < result.size() - 1; i++) { // result.get(i).next = result.get(i+1); // } // result.get(result.size() - 1).next = null; // // return result.get(0).next; // }
// public ListNode deleteDuplication(ListNode pHead){ // ListNode tHead = new ListNode(Integer.MIN_VALUE),t; // boolean isRepeated; // tHead.next = pHead; // // pHead = tHead; // while (pHead != null){ // isRepeated = false; // // t = pHead.next; // if (t == null) break; // // while (t.val == pHead.val){ // isRepeated = true; // t = t.next; // if (t == null){ // pHead.next = null; // break; // } // } // // pHead.next = t; // if (isRepeated) pHead.val = Integer.MAX_VALUE; // pHead = pHead.next; // } // // pHead = tHead; // while (pHead != null){ // if (pHead.next == null) break; // else if (pHead.next.val == Integer.MAX_VALUE){ // pHead.next = pHead.next.next; // }else { // pHead = pHead.next; // } // } // // return tHead.next; // }