链表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 }
本文来自博客园,作者:Ricentch,转载请注明原文链接:https://www.cnblogs.com/cnwsh/p/16565368.html

浙公网安备 33010602011771号