203.移除链表元素
题意:删除链表中等于给定值 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
输出:[]
思路:
方法一:递归
方法二:迭代
删除链表中给定值的节点,一般的步骤是:
遍历链表找到所有值为 val 的节点;
将值为 val 的节点的上一个节点直接指向该节点的下一个节点(pre->next = pre->next->next)。
方法三:双指针
解题步骤:
设置两个均指向头节点的指针,pre(记录待删除节点的前一节点)和 cur (记录当前节点);
遍历整个链表,查找节点值为 val 的节点,找到即删除该节点,否则继续查找。
2.1 找到,将当前节点的前一节点(之前最近一个值不等于 val 的节点(pre))连接到当前节点(cur)的下一个节点(即将 pre 的下一节点指向 cur 的下一节点:pre->next = cur->next)。
2.2 没找到,更新最近一个值不等于 val 的节点(即 pre = cur),并继续遍历(cur = cur->next)。
方法四:虚拟头节点(哨兵)
前三种方法均需要判断头节点是否为待删除的节点,且处理头节点的代码逻辑与其它节点特别相似,有没有方法使得代码更优美并且能避免对头节点的判断呢?
答案是有的。可以通过在头节点前增加虚拟头节点,这样头节点就成了普通节点,不需要单独拎出来考虑,但是在返回的时候,返回的是虚拟头节点的下一节点而不是虚拟头节点。
方法五:栈
本题还可以采用栈去做。
-
将值不等于 val 的节点依次压入栈中;
-
将压入栈的节点重新连接,栈底的节点作为新的头节点返回
1 #include<vector> 2 #include<iostream> 3 #include<algorithm> 4 #include<numeric> 5 #include<iterator> 6 #include<stack> 7 using namespace std; 8 9 struct ListNode { 10 int val; 11 ListNode *next; 12 ListNode() : val(0), next(nullptr) {} 13 ListNode(int x) : val(x), next(nullptr) {} 14 ListNode(int x, ListNode *next) : val(x), next(next) {} 15 }; 16 17 class Solution { 18 public: 19 ListNode* removeElements_doublezhizhen(ListNode* head, int val) 20 { 21 while(head!=nullptr && head->val==val) 22 { 23 head = head->next; 24 } 25 if (head == nullptr) return head; 26 ListNode* pre = head; 27 ListNode* cur = head; 28 while(cur != nullptr) 29 { 30 cur = cur->next; 31 if(cur->val == val) 32 { 33 pre->next = cur->next; 34 cur = pre->next; 35 } 36 else 37 { 38 pre = pre->next; 39 } 40 } 41 return head; 42 } 43 ListNode* removeElements_digui(ListNode* head, int val) 44 { 45 if(head == nullptr) 46 { 47 return head; 48 } 49 head->next = removeElements_digui(head->next,val); 50 return head->val == val? head->next:head; 51 } 52 ListNode* removeElements_diedai(ListNode* head, int val) 53 { 54 while(head!=nullptr&&head->val==val) 55 { 56 head = head->next; 57 } 58 if(head==nullptr) 59 { 60 return head; 61 } 62 ListNode*pre = head; 63 while(pre->next!=nullptr) 64 { 65 if(pre->next->val==val) 66 { 67 pre->next = pre->next->next; 68 } 69 else 70 { 71 pre = pre->next; 72 } 73 } 74 return head; 75 } 76 ListNode* removeElements_dummyhead(ListNode* head, int val) 77 { 78 ListNode* dummy_head = new ListNode(0,head); 79 ListNode* cur = dummy_head; 80 while(cur->next) 81 { 82 if(cur->next->val==val) 83 { 84 ListNode* delete_node = cur->next; 85 cur->next = delete_node->next; 86 delete delete_node; 87 } 88 else 89 { 90 cur = cur->next; 91 } 92 } 93 ListNode* res = dummy_head->next; 94 delete dummy_head; 95 return res; 96 } 97 ListNode* removeElements_stack(ListNode* head, int val) 98 { 99 stack<ListNode*>* sta = new stack<ListNode*>(); 100 while(head!=nullptr) 101 { 102 if(head->val!=val) 103 { 104 (*sta).push(head); 105 } 106 head = head->next; 107 } 108 while(!(*sta).empty()) 109 { 110 ((*sta).top())->next = head; 111 head = (*sta).top(); 112 (*sta).pop(); 113 } 114 return head; 115 } 116 }; 117 118 int main() { 119 ListNode* head = new ListNode(); 120 ListNode* r = nullptr; 121 vector<int> num = { 1,2,7,7,7,7 }; 122 for (int i =num.size()-1;i>=0;i--) 123 { 124 ListNode* a = new ListNode(num[i],r); 125 head->next = a; 126 r = a; 127 } 128 for (auto p = head->next; p != nullptr; p = p->next) 129 { 130 cout << p->val; 131 } 132 cout << endl; 133 ListNode* res = new ListNode(); 134 Solution a; 135 res = a.removeElements_stack(head,7); 136 for (auto p = head->next; p != nullptr; p = p->next) 137 { 138 cout << head->next->val; 139 head = head->next; 140 } 141 cout << endl; 142 system("pause"); 143 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理