思路一:
遍历链表,把遍历的值存储到一个Hashtable中,在遍历过程中,若当前访问的值在Hashtable中已经存在,则说明这个数据是重复的,因此就可以删除。
优点:时间复杂度较低O(n)
缺点:在遍历过程中需要额外的存储空间来保存已遍历过的值
思路二:
对链表进行双重循环遍历,外循环正常遍历链表,假设外循环当前遍历的结点为cur,内循环从cur开始遍历,若碰到与cur所指向结点值相同,则删除这个重复结点
优点:不需要额外的存储空间
缺点:时间复杂度较高O(n^2)
思路三:
外循环当前遍历的结点为cur,内循环从链表头开始遍历至cur,只要碰到与cur值相同的结点就删除该结点,同时内循环结束,因为与cur相同的结点只可能存在一个(如果存在多个,在前面的遍历过程中已经被删除了)
优点:采用这种方法在特定的数据发布的情况下会提高算法的时间复杂度
import java.util.*;
/**
* @author
* @date
* @function 从链表中删除重复元素
*/
public class deleteDuplecate {
//法一:优点是时间复杂度低,但是需要额外的存储空间来保存遍历过的值。时间复杂度O(n)
public void delete_v1(Node head){
Hashtable<Integer,Integer> table=new Hashtable<Integer,Integer>();
Node temp=head;
Node pre=null; //辅助链表的头节点
while(temp!=null){
if(table.containsKey(temp.data))
pre.next=temp.next;
else{
table.put(temp.data, 1);
pre=temp;
}
temp=temp.next;
}
}
//法二:双重循环遍历链表,优点:不需要额外的存储空间.时间复杂度O(n^2)
public void delete_v2(Node head){
Node p=head;
while(p!=null){
Node q=p;
while(q.next!=null){
if(q.next.data==p.data){
q.next=q.next.next;
}else
q=q.next;
}
p=p.next;
}
}
//法三:外循环当前遍历的结点为p,内循环从表头开始遍历至p
public void delete_v3(Node head){
Node p=head;
while(p!=null){
Node q=head;
while(q.next!=p && q.next!=null){
if(q.next.data==p.data){
q.next=q.next.next;
}else
q=q.next;
}
p=p.next;
}
}
}
class Node{
Node next=null;
int data;
public Node(int data){
this.data=data;
}
}