題目
編寫代碼,移除未排序鏈表中的重複節點。保留最開始出現的節點。
示例1:
輸入:[1, 2, 3, 3, 2, 1]
輸出:[1, 2, 3]
示例2:
輸入:[1, 1, 1, 1, 2]
輸出:[1, 2]
提示:
鏈表長度在[0, 20000]範圍內。
鏈表元素在[0, 20000]範圍內。
進階:
如果不得使用臨時緩衝區,該怎麼解決?
鏈接:https://leetcode-cn.com/problems/remove-duplicate-node-lcci
解題記錄
- 通過set記錄出現過的值,重複的跳過
import java.util.HashSet;
import java.util.Set;
/**
* @author ffzs
* @describe
* @date 2020/6/26
*/
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class Solution {
public ListNode removeDuplicateNodes(ListNode head) {
if (head == null) return null;
ListNode tmp = head;
Set<Integer> valSet = new HashSet<>();
valSet.add(tmp.val);
while (tmp.next!= null) {
if (valSet.contains(tmp.next.val)) {
tmp.next = tmp.next.next ;
}else{
valSet.add(tmp.next.val);
tmp = tmp.next;
}
}
return head;
}
}
優化
- 因爲本題限定了數取值的大小,可以構建一個定長數組
new boolean[20001]
來存儲數值的出現情況,這樣避免了使用set包裝器轉換帶來的消耗
/**
* @author ffzs
* @describe
* @date 2020/6/26
*/
public class Solution2 {
public ListNode removeDuplicateNodes(ListNode head) {
if (head == null) return null;
ListNode tmp = head;
boolean[] valList = new boolean[20001];
valList[head.val] = true;
while (tmp.next!= null) {
if (valList[tmp.next.val]) {
tmp.next = tmp.next.next ;
}else{
valList[tmp.next.val] = true;
tmp = tmp.next;
}
}
return head;
}
}
進階
- 要不使用緩存的話就不能使用set,list這些存儲節點
- 有個思路是,通過冒泡排序的方法,一邊對比排序一邊去掉重複的值,但是頭結點不能變,是不是不能改變出現順序
- 還有一個方法就是通過遍歷該節點之後的節點,有重複的直接去掉,不過速度很慢就是了,節省了空間
/**
* @author ffzs
* @describe
* @date 2020/6/26
*/
public class Solution3 {
public ListNode removeDuplicateNodes(ListNode head) {
if (head == null) return null;
ListNode tmp = head;
while (tmp != null) {
ListNode t = tmp;
while (t.next != null) {
if (t.next.val == tmp.val) {
t.next = t.next.next;
}
else {
t = t.next;
}
}
tmp = tmp.next;
}
return head;
}
}
- 想了一下如果可以改變出現順序的話,可以從head的下一個開始進行冒泡排序處理,如果該節點的值或head的值和next的值相同,直接刪掉next,如果大於next值,交換位置,如果小於跳到next
- 不過這裏交換的話需要上一節點,可以使用next和next.next進行比較
- 重複多次,知道不再發生交換,返回head