程序運行截圖:
public class Node {
public static final int HEAD = 0X66;
public int value;
public int count;
public Node preNode;
public Node nextNode;
public Node() {}
public Node(int value,Node nextNode) {
this.value = value;
this.nextNode = nextNode;
}
}
package algorithm2;
public class Algorithm2 {
/*
* [刪除鏈表中重複的結點]
*
* [題目] 在一個排序的鏈表中,存在重複的結點,請刪除該鏈表中重複的結點,重複的結點不保留,返回鏈表頭指針。
* 例如,鏈表1->2->3->3->4->4->5 處理後爲 1->2->5
*
* [解析] 主要考代碼的能力,注意邊界條件的考慮,指針判空等。
*/
public static void main(String[] args) {
Node testNode = createTestLinked();
printNode(testNode);
testNode = filterNode(testNode);
printNode(testNode);
}
/**
* 創建測試鏈表
* 爲了方便最後返回鏈表頭指針,我給鏈表創建了一個 HEAD 節點->
* 這樣不管後面的節點如何變動,我只要保證結果鏈表的結果正確,並且與 HEAD 節點依然鏈接在一起就好了
* @return
*/
private static Node createTestLinked() {
Node node5 = new Node(5, null);
Node node4_2 = new Node(4, node5);
Node node4_1 = new Node(4, node4_2);
Node node3_2 = new Node(3, node4_1);
Node node3_1 = new Node(1, node3_2);
Node node2 = new Node(2, node3_1);
Node node1 = new Node(2, node2);
node5.preNode = node5;
node4_2.preNode = node4_1;
node4_1.preNode = node3_2;
node3_2.preNode = node3_1;
node3_1.preNode = node2;
node2.preNode = node1;
Node headNode = new Node(Node.HEAD, node1);
node1.preNode = headNode;
return headNode;
}
/**
* 打印鏈表,不打印 HEAD 節點
* @param node
*/
private static void printNode(Node node) {
Node preNode = node.nextNode;
StringBuilder sb = new StringBuilder();
sb.append(preNode.value + ":: count = " + preNode.count + "-> ");
while (preNode.nextNode != null) {
sb.append(preNode.nextNode.value + ":: count = " + preNode.nextNode.count + "-> ");
preNode = preNode.nextNode;
}
System.out.println(sb.toString());
}
/**
* 刪除重複節點的方法,可惜的是這個方法的時間複雜度是 O(n^2)
*
* 其實還有一種有缺陷的思路 ->
* 那就類似於桶排序的思路:
* 如果知道取值value的取值範圍,並且跨度不大,在能接受範圍內的話->
* 可以以value爲index,爲這個鏈表的值創建一個數組,而數組的內容則是index作爲value出現在鏈表中的次數->
* 然後遍歷鏈表,將其與數組互爲對照,這樣也能知道重複的節點。然後由於這個方法的侷限性和缺陷就不編碼了。->
* 然而,一旦符合上面的一些限制,那麼這個思路的時間複雜度 O(n)
* @param node
* @return
*/
private static Node filterNode(Node node) {
Node compare = node.nextNode;
// 在 Node 節點中設置標記,在將每一個節點依次拿出來與所有節點對比時,如果相等標記遞增
while (compare != null) {
Node nextNode = node.nextNode;
while (nextNode != null) {
if (nextNode.value == compare.value) {
compare.count++;
}
nextNode = nextNode.nextNode;
}
compare = compare.nextNode;
}
// 在全部比較之後再將重複的節點調節
compare = node.nextNode;
while(compare != null) {
if(compare.count != 1) {
compare.preNode.nextNode = compare.nextNode;
compare.nextNode.preNode = compare.preNode;
}
compare = compare.nextNode;
}
return node;
}
}