题目:
Given a sorted linked list, delete all duplicates such that each element appear only once.
Example 1:
Input: 1->1->2
Output: 1->2
Example 2:
Input: 1->1->2->3->3
Output: 1->2->3
2022.12.18
时隔两年这题又不会写了……刚开始写了个巨麻烦的解法,造了一个新的链表然后把当前链表里的copy过去……看了下两年前的解法觉得两年前的自己真机智啊……然后看了别人的解法发现别人也很机智。
自己两年前的解法的思想是,写一个内层while循环跳过所有一样的val:如果curr和curr.next val一样的话,就把curr.next.next当成curr.next,跳过curr.next这个val一样的节点,直到它们不一样为止,那curr.next就是另一个val了,就可以接着外层while循环。代码看下面。
上面这种思想也可以不采用内层的while循环,而是用if-else代替:
class Solution {
public ListNode deleteDuplicates(ListNode head) {
ListNode curr = head;
while (curr != null) {
if (curr.next != null && curr.val == curr.next.val) {
curr.next = curr.next.next;
} else {
curr = curr.next;
}
}
return head;
}
}
另一种是递归的解法,递归的终止条件是如果head == null或者只有一个节点了(head.next == null)。因为这个函数每次会返回以当前head为起始的符合条件的链表,所以应该head.next = deleteDuplicates(head.next),最后根据head.val是否等于head.next.val,决定应该返回head还是head.next作为最终的返回值。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if (head == null || head.next == null) {
return head;
}
head.next = deleteDuplicates(head.next);
if (head.val == head.next.val) {
return head.next;
} else {
return head;
}
}
}
2020.10.14 Java
直接一遍bug free写出了最优解哈哈哈哈
Runtime: 0 ms, faster than 100.00% of Java online submissions for Remove Duplicates from Sorted List.
Memory Usage: 38.4 MB, less than 12.15% of Java online submissions for Remove Duplicates from Sorted List.
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
ListNode curr = head;
while (curr != null) {
while (curr.next != null && curr.val == curr.next.val) {
curr.next = curr.next.next;
}
curr = curr.next;
}
return head;
}
}
以下是曾经的菜鸡笔记
这道题又是链表的题,刚开始一看到链表就怕,后来还是自己尝试了一下,发现这道题还是很简单的,但是依旧是自己第一遍写的代码有点问题,最终代码如下,时间复杂度O(n),运行时间8ms,只打败了37.76%:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if (head == NULL) return NULL;
ListNode* current = head;
while (current->next != NULL) {
ListNode* nextNode = current->next;
if (current->val == nextNode->val) {
current->next = nextNode->next;
}
else {
current = current->next;
}
}
return head;
}
};
主要问题有两个:
1. 刚开始没有单独把head提出来存到一个current里面,导致最后return head的时候return的是最后一个ListNode而不是整个链表。总结一下,如果把一个ListNode a赋值给ListNode b,那么a后面的所有节点都会赋值给b,并且只要b变了,a也跟着变。具体这样的原因我还没有理解透彻,待我回头复习数据结构到链表的时候再回来填坑吧……(又双叒给自己留了坑等着填,唉)
2. 第一次提交时出错的test case是[1, 1, 1],我返回的是[1, 1],想了很久没想到原因,仔细比对了discussion里的代码才发现。其实while循环里面有两种写法,一种是采用if-else,也就是我现在采用的方法,刚开始出错的原因在于没有加else,想着应该不管怎么样都要让current指向下一个,但是出错后在纸上一画发现确实,第一个if里面已经把current->next指向了最后一个1,而如果再让current = current->next的话那么就不会进入下一个循环了,如果在else里面加入这一句的话,就相当于当前这个第一个遇到的非重复的数字不断地与它的下一个比较,这个小细节一直都没注意到。另外一种做法就是在把if换成while,这样的话原先else里面那句话就不用放在while里面,也是相当于不断地删掉下一个与current相同的数字,直到不同以后再跳转到下一个循环中,代码如下,运行时间4ms,瞬间变最快:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* current = head;
while (current != NULL) {
while (current->next != NULL && current->val == current->next->val) {
current->next = current->next->next;
}
current = current->next;
}
return head;
}
};