Leetcode 203 Remove Linked List Elements
Remove all elements from a linked list of integers that have value val. For example, given 1 -> 2 -> 6 -> 3 -> 4 -> 5 -> 6, val = 6. Return 1 -> 2 -> 3 -> 4 -> 5.
分析与解法
遍历链表,用一个指针指向遍历到当前结点的前驱结点,方便删除;如果当前结点的值为val,则删除。参考代码如下所示:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode 4 * { 5 * int val; 6 * ListNode *next; 7 * ListNode(int x) : val(x), next(NULL) {} 8 * }; 9 */ 10 class Solution 11 { 12 public: 13 ListNode* removeElements(ListNode* head, int val) 14 { 15 ListNode new_head_node(0); new_head_node.next = head; 16 ListNode *pre = &new_head_node, *p = head; 17 while (p) 18 { 19 if (p->val == val) 20 { 21 ListNode *q = p; 22 p = p->next; 23 pre->next = p; 24 delete q; // 释放结点 25 } 26 else 27 { 28 pre = p; 29 p = p->next; 30 } 31 } 32 return new_head_node.next; 33 } 34 };
Leetcode 83 Remove Duplicates from Sorted List
Given a sorted linked list, delete all duplicates such that each element appear only once. For example, given 1 -> 1 -> 2, return 1 -> 2. Given 1 -> 1 -> 2 -> 3 -> 3, return 1 -> 2 -> 3.
分析与解法
遍历链表,查看当前结点的值是否与其前驱结点相同,如果相同,则删除;否则不删除。参考代码如下:
1 class Solution 2 { 3 public: 4 ListNode* deleteDuplicates(ListNode* head) 5 { 6 if (!head || !head->next) return head; 7 ListNode *pre = head, *p = head->next; 8 while (p) 9 { 10 if (p->val == pre->val) 11 { 12 ListNode *q = p; 13 p = p->next; 14 pre->next = p; 15 delete q; 16 } 17 else 18 { 19 pre = p; 20 p = p->next; 21 } 22 } 23 return head; 24 } 25 };
Leetcode 82 Remove Duplicates from Sorted List II
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. For example, given 1 -> 2 -> 3 -> 3 -> 4 -> 4 -> 5, return 1 -> 2 -> 5. Given 1 -> 1 -> 1 -> 2 -> 3, return 2 -> 3.
分析与解法
(1) 非递归解法
遍历链表,看当前结点值是否与后继结点值相等(如果后继不为空),如果不相等,则继续遍历;否则,删除与当前结点值相同的所有结点,包括当前结点,使用一个指针指向遍历到当前结点的前驱结点,方便进行删除操作。参考代码如下:
1 class Solution 2 { 3 public: 4 ListNode* deleteDuplicates(ListNode* head) 5 { 6 ListNode new_head_node(0); new_head_node.next = head; 7 ListNode *pre = &new_head_node, *p = head; 8 while (p && p->next) 9 { 10 if (p->val != p->next->val) 11 { 12 pre->next = p; 13 pre = p; 14 p = p->next; 15 } 16 else 17 { 18 while (p && p->next && p->val == p->next->val) 19 { 20 ListNode *q = p; 21 p = p->next; 22 delete q; 23 } 24 if (p) 25 { 26 ListNode *q = p; 27 pre->next = p->next; 28 p = p->next; 29 delete q; 30 } 31 else pre->next = NULL; 32 } 33 } 34 return new_head_node.next; 35 } 36 };
(2) 递归解法
一个看起来更容易理解的方法,参考代码如下:
1 class Solution 2 { 3 public: 4 ListNode* deleteDuplicates(ListNode* head) 5 { 6 if (!head || !head->next) return head; 7 ListNode *p = head; 8 if (p->val != p->next->val) 9 { 10 p->next = deleteDuplicates(p->next); 11 return head; 12 } 13 else 14 { 15 while (p->next && p->val == p->next->val) 16 { 17 ListNode *q = p; 18 p = p->next; 19 delete q; 20 } 21 ListNode *q = p->next; 22 delete p; 23 return deleteDuplicates(q); 24 } 25 } 26 };
Leetcode 19 Remove Nth Node fron End of List
Given a linked list, remove the Nth node from the end of list and return its head. For example, given linked list: 1 -> 2 -> 3 -> 4 -> 5, and n = 2. After removing the second node from the end, the linked list becomes 1 -> 2 -> 3 -> 5.
Note: given n will always be valid. Try to do this in one pass.
分析与解法
经典的快慢指针问题,先用快慢指针找到倒数第n个结点的前驱结点,然后删除,参考代码如下所示:
1 class Solution 2 { 3 public: 4 ListNode* removeNthFromEnd(ListNode* head, int n) 5 { 6 ListNode *nhead = new ListNode(0); nhead->next = head; 7 ListNode *p = head, *q = nhead, *s = NULL; 8 for (int i = 0; i < n; i++) p = p->next; 9 while (p) 10 { 11 p = p->next; 12 q = q->next; 13 } 14 s = q->next; 15 q->next = s->next; 16 delete s; 17 return nhead->next; 18 } 19 };
Leetcode 237 Delete Node in a Linked List
Write a function to delete a node (except the tail) in a singly linked list, given only access to that node. Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.
分析与解法
在删除结点时,如果我们知道要删除结点的前驱结点,那么,删除这个结点将比较容易,换句话说,删除一个结点的后继结点是比较容易实现的;而本题并不知道前驱,也没有办法获得前驱结点的位置。可以换一个思路,将当前结点的后继删除,这是比较容易做到的,不过,在删除其后继结点之前,需要将后继结点的值赋给当前结点,这样虽然删除的是其后继,但实际保留了后继的值,删除了当前结点的值。参考代码如下所示:
1 class Solution { 2 public: 3 void deleteNode(ListNode* node) 4 { 5 node->val = node->next->val; 6 ListNode *s = node->next; 7 node->next = s->next; 8 delete s; 9 } 10 };