链表1:移除链表元素(203)

本题如下:(链接:https://leetcode.cn/problems/remove-linked-list-elements/)

题目:给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例 2:
输入:head = [], val = 1
输出:[]

示例 3:
输入:head = [7,7,7,7], val = 7
输出:[]

 

思路:

首先以链表 1 4 2 4 来举例,移除元素4。

 

 如果使用C++编程语言的话,不要忘了还要从内存中删除这两个移除的节点, 清理节点内存之后如下图所示:

 

 

而如果使用java ,python的话就不用手动管理内存了。

还要说明一下,就算使用C++来做Leetcode,如果移除一个节点之后,没有手动在内存中删除这个节点,Leetcode依然也是可以通过的,只不过,内存使用的空间大一些而已,但建议依然要养成手动清理内存的习惯。

这种情况下的移除操作,就是让节点next指针直接指向下下一个节点就可以了,

但是由于单链表的特殊性,只能指向下一个节点,刚刚删除的是链表的中第二个,和第四个节点,而如果删除的是头结点其方法又不一样:

这里就涉及链表操作的两种方式:(1)直接使用原来的链表来进行删除操作。(2)设置一个虚拟头结点在进行删除操作。

 

第一种操作:直接使用原来的链表来进行移除。

移除头结点和移除其他节点的操作是不一样的,因为链表的其他节点都是通过前一个节点来移除当前节点,而头结点没有前一个节点。

所以头结点如何移除呢,其实只要将头结点向后移动一位就可以,这样就从链表中移除了一个头结点。

 

但 依然建议将原头结点从内存中删掉。

 

 

这样移除了一个头结点,可以发现,在单链表中,移除头结点 和 移除其他节点的操作方式是不一样,其实在写代码的时候也会发现,需要单独写一段逻辑来处理移除头结点的情况。

这样我们就自然会想,有没有以一种统一的逻辑来移除 链表的节点的方法。

 

这就是我们要说的第二种操作:设置一个虚拟头结点在进行删除操作。

设置一个虚拟头结点,这样原链表的所有节点就都可以按照统一的方式进行移除了。

我们依然是以在这个链表中,移除元素1为例。

 

 

如上图所示,这里来给链表添加一个虚拟头结点为新的头结点,此时要移除这个旧头结点元素1。

这里要移除元素1 呢,还是熟悉的方式,然后从内存中删除元素1。

而最后在题目中,return 头结点的时候,还需要 return dummyNode->next;, 这才是新的头结点。

 

下面给出两种操作相应的C++代码:

1.直接使用原来的链表来进行移除节点操作:

 1 class Solution {
 2 public:
 3     ListNode* removeElements(ListNode* head, int val) {
 4         // 删除头结点
 5         while (head != NULL && head->val == val) { // 注意这里不是if
 6             ListNode* tmp = head;
 7             head = head->next;
 8             delete tmp;
 9         }
10 
11         // 删除非头结点
12         ListNode* cur = head;
13         while (cur != NULL && cur->next!= NULL) {
14             if (cur->next->val == val) {
15                 ListNode* tmp = cur->next;
16                 cur->next = cur->next->next;
17                 delete tmp;
18             } else {
19                 cur = cur->next;
20             }
21         }
22         return head;
23     }
24 };

2.设置一个虚拟头结点在进行移除节点操作:

 1 class Solution {
 2 public:
 3     ListNode* removeElements(ListNode* head, int val) {
 4         ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
 5         dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
 6         ListNode* cur = dummyHead;
 7         while (cur->next != NULL) {
 8             if(cur->next->val == val) {
 9                 ListNode* tmp = cur->next;
10                 cur->next = cur->next->next;
11                 delete tmp;
12             } else {
13                 cur = cur->next;
14             }
15         }
16         head = dummyHead->next;
17         delete dummyHead;
18         return head;
19     }
20 };

 

另外,还给出该题的Java代码:

 1 /**
 2  * 添加虚节点方式
 3  * 时间复杂度 O(n)
 4  * 空间复杂度 O(1)
 5  * @param head
 6  * @param val
 7  * @return
 8  */
 9 public ListNode removeElements(ListNode head, int val) {
10     if (head == null) {
11         return head;
12     }
13     // 因为删除可能涉及到头节点,所以设置dummy节点,统一操作
14     ListNode dummy = new ListNode(-1, head);
15     ListNode pre = dummy;
16     ListNode cur = head;
17     while (cur != null) {
18         if (cur.val == val) {
19             pre.next = cur.next;
20         } else {
21             pre = cur;
22         }
23         cur = cur.next;
24     }
25     return dummy.next;
26 }
27 /**
28  * 不添加虚拟节点方式
29  * 时间复杂度 O(n)
30  * 空间复杂度 O(1)
31  * @param head
32  * @param val
33  * @return
34  */
35 public ListNode removeElements(ListNode head, int val) {
36     while (head != null && head.val == val) {
37         head = head.next;
38     }
39     // 已经为null,提前退出
40     if (head == null) {
41         return head;
42     }
43     // 已确定当前head.val != val
44     ListNode pre = head;
45     ListNode cur = head.next;
46     while (cur != null) {
47         if (cur.val == val) {
48             pre.next = cur.next;
49         } else {
50             pre = cur;
51         }
52         cur = cur.next;
53     }
54     return head;
55 }
56 /**
57  * 不添加虚拟节点and pre Node方式
58  * 时间复杂度 O(n)
59  * 空间复杂度 O(1)
60  * @param head
61  * @param val
62  * @return
63  */
64 public ListNode removeElements(ListNode head, int val) {
65     while(head!=null && head.val==val){
66         head = head.next;
67     }
68     ListNode curr = head;
69     while(curr!=null){
70         while(curr.next!=null && curr.next.val == val){
71             curr.next = curr.next.next;
72         }
73         curr = curr.next;
74     }
75     return head;
76 }

 

posted @ 2022-08-09 11:31  Ricentch  阅读(50)  评论(0)    收藏  举报