本文參考自《劍指offer》一書,代碼采用Java語言。
題目
在一個排序的鏈表中,如何刪除重復的結點?例如,在圖3.4(a)中重復結點被刪除之后,鏈表如圖3.4(b)所示。
思路
設置一個preNode,用於記錄當前結點的前一個結點,再設置一個布爾變量needDelete,如果當前結點和后一結點的值相同(記該值為dupVal),needDelete賦值為真。
當needDelete為真時,通過循環往后找到第一個不為dupVal的結點,把該結點設置為當前結點,並賦值給preNode.next,即相當於完成了刪除操作;而當needDelete為假時,把當前結點和preNode往后移一位即可。
測試算例
1.功能測試(重復結點位於鏈表頭部、中部、尾部,無重復結點)
2.特殊測試(null,所有結點均重復)
完整Java代碼
public ListNode deleteDuplication(ListNode pHead){ ListNode pre = null; ListNode cur = pHead; while(cur!=null){ if(cur.next!=null && cur.next.val==cur.val){ while(cur.next!=null && cur.next.val==cur.val) cur=cur.next; cur=cur.next; if(pre==null) pHead=cur; else pre.next=cur; }else{ pre=cur; cur=cur.next; } } return pHead; }
(含測試代碼)
package _18;
/**
*
* @Description 面試題18(二):刪除鏈表中重復的結點
*
* @author yongh
* @date 2018年9月18日 下午6:30:53
*/
// 題目:在一個排序的鏈表中,如何刪除重復的結點?例如,在圖3.4(a)中重復
// 結點被刪除之后,鏈表如圖3.4(b)所示。
public class DeleteDuplicatedNode {
class ListNode{
int val;
ListNode next = null;
ListNode(int val,ListNode next) {
this.val = val;
this.next=next;
}
}
public ListNode deleteDuplication(ListNode pHead){
if(pHead==null||pHead.next==null) //空結點或者僅一個結點
return pHead;
ListNode preNode = null;
ListNode curNode = pHead;
while(curNode!=null){
boolean needDelete=false;
if(curNode.next!=null && curNode.val==curNode.next.val)
needDelete=true;
if(!needDelete){ //當前結點不重復
preNode=curNode;
curNode=curNode.next;
}else{ //當前結點重復
int dupValue=curNode.val;
ListNode toBeDel = curNode;
while(toBeDel!=null&&toBeDel.val==dupValue){
//這里刪除暫時不涉及前一結點操作,其實主要是找出后面第一個不重復結點
toBeDel = toBeDel.next;
}
if(preNode==null){ //說明刪除的結點為頭結點
pHead=toBeDel;
}else{
preNode.next=toBeDel;
}
curNode=toBeDel; //這個結點還是可能會出現重復的,所以不能=next
}
}
return pHead;
}
//========測試代碼======
void test(ListNode pHead) {
System.out.println("-----------");
System.out.print("The original list is: ");
ListNode curr=pHead;
if(curr!=null) {
while(curr.next!=null) {
System.out.print(curr.val+",");
curr=curr.next;
}
System.out.println(curr.val);
}else {
System.out.println();
}
pHead=deleteDuplication(pHead);
System.out.print("The result list is: ");
curr=pHead;
if(curr!=null) {
while(curr.next!=null) {
System.out.print(curr.val+",");
curr=curr.next;
}
System.out.println(curr.val);
}else {
System.out.println();
}
System.out.println("-----------");
}
/**
* 重復結點位於鏈表頭部
*/
void test1() {
ListNode p4=new ListNode(3, null);
ListNode p3=new ListNode(2, p4);
ListNode p2=new ListNode(1, p3);
ListNode p1=new ListNode(1, p2);
test(p1);
}
/**
* 重復結點位於鏈表尾部
*/
void test2() {
ListNode p4=new ListNode(3, null);
ListNode p3=new ListNode(3, p4);
ListNode p2=new ListNode(2, p3);
ListNode p1=new ListNode(1, p2);
test(p1);
}
/**
* 重復結點位於鏈表中部
*/
void test3() {
ListNode p4=new ListNode(3, null);
ListNode p3=new ListNode(2, p4);
ListNode p2=new ListNode(2, p3);
ListNode p1=new ListNode(1, p2);
test(p1);
}
/**
* 連續出現重復結點
*/
void test4() {
ListNode p6=new ListNode(3, null);
ListNode p5=new ListNode(3, p6);
ListNode p4=new ListNode(2, p5);
ListNode p3=new ListNode(2, p4);
ListNode p2=new ListNode(1, p3);
ListNode p1=new ListNode(1, p2);
test(p1);
}
/**
* 多個重復結點
*/
void test5() {
ListNode p6=new ListNode(3, null);
ListNode p5=new ListNode(3, p6);
ListNode p4=new ListNode(3, p5);
ListNode p3=new ListNode(2, p4);
ListNode p2=new ListNode(1, p3);
ListNode p1=new ListNode(1, p2);
test(p1);
}
/**
* 無重復結點
*/
void test6() {
ListNode p6=new ListNode(6, null);
ListNode p5=new ListNode(5, p6);
ListNode p4=new ListNode(4, p5);
ListNode p3=new ListNode(3, p4);
ListNode p2=new ListNode(2, p3);
ListNode p1=new ListNode(1, p2);
test(p1);
}
/**
* 單個結點
*/
void test7() {
ListNode p1=new ListNode(6, null);
test(p1);
}
/**
* null
*/
void test8() {
ListNode p1=null;
test(p1);
}
public static void main(String[] args) {
DeleteDuplicatedNode demo= new DeleteDuplicatedNode();
demo.test1();
demo.test2();
demo.test3();
demo.test4();
demo.test5();
demo.test6();
demo.test7();
demo.test8();
}
}
----------- The original list is: 1,1,2,3 The result list is: 2,3 ----------- ----------- The original list is: 1,2,3,3 The result list is: 1,2 ----------- ----------- The original list is: 1,2,2,3 The result list is: 1,3 ----------- ----------- The original list is: 1,1,2,2,3,3 The result list is: ----------- ----------- The original list is: 1,1,2,3,3,3 The result list is: 2 ----------- ----------- The original list is: 1,2,3,4,5,6 The result list is: 1,2,3,4,5,6 ----------- ----------- The original list is: 6 The result list is: 6 ----------- ----------- The original list is: The result list is: -----------
收獲
1.刪除多個結點時,只要把重復結點前一個結點的next指向重復結點的后一個結點;
2.不要把重復結點一個一個刪除,先定義一個布爾變量確定當前結點是否重復,然后按上一句話的方法進行刪除即可。
