203 移除链表元素 | 707 设计链表 | 206 反转链表

783 阅读3分钟

移除链表元素

题目描述:给定一个链表的头节点 head 和一个整数 val,让删除链表中所有满足 Node->val == val 的节点,并返回新的头结点。

思路

删除链表结点: p->next = p->next->next 其中 p->next 的值等于val

从前到后依次遍历每个节点,若值等于val,删除即可。

代码

1.迭代

 /**
  * Definition for singly-linked list.
  * struct ListNode {
  *     int val;
  *     ListNode *next;
  *     ListNode() : val(0), next(nullptr) {}
  *     ListNode(int x) : val(x), next(nullptr) {}
  *     ListNode(int x, ListNode *next) : val(x), next(next) {}
  * };
  */
 class Solution {
 public:
     ListNode* removeElements(ListNode* head, int val) {
         ListNode* dummyNode = new ListNode(-1, head);
         ListNode* p = dummyNode;
         while (p->next != NULL)
         {
             ListNode* item = p->next;
             if (item->val == val)
             {
                 p->next = item->next;
                 delete item;
             }
             else
                 p = item;
         }
         return dummyNode->next;
     }
 };

3.递归

相当于从后往前依次处理节点

模版:

 void fun(LinkNode* head)
 {
     if (head == NULL)
         return head;
   
     // 前序遍历
     fun(head->next);
     // 后序遍历
 }

对head的操作相当于对所有链表上其他节点的操作

 /**
  * Definition for singly-linked list.
  * struct ListNode {
  *     int val;
  *     ListNode *next;
  *     ListNode() : val(0), next(nullptr) {}
  *     ListNode(int x) : val(x), next(nullptr) {}
  *     ListNode(int x, ListNode *next) : val(x), next(next) {}
  * };
  */
 class Solution {
 public:
     ListNode* removeElements(ListNode* head, int val) {
         if (head == NULL)
             return head;
         
         head->next = removeElements(head->next, val);
         if (head->val != val)
             return head;
         else 
             return head->next;
     }
 };

设计链表

题目描述:设计一个链表类,实现 get(index), addAtHead(val), addAtTail(val), addAtIndex(index, val), deleteAtIndex(index)这些功能。

思路

代码

 class MyLinkedList {
 struct Node
 {
     int val;
     Node* next;
     Node(int val) : val(val), next(NULL) {};
     Node(int val, Node* next)
     {
         val = val;
         next = next;
     }
 };
 ​
 private:
     int _size;  // 链表长度
     Node* _dummyNode;  // 头节点
 ​
 public:
     MyLinkedList() {
         _size = 0;
         _dummyNode = new Node(-1);
     }
     
     int get(int index) {
         if (index < 0 || index >= _size)
             return -1;
         Node* p = _dummyNode;
         for (int i = 0; i < index; i++)
             p = p->next;
         return p->next->val;
     }
     
     void addAtHead(int val) {
         Node* item = new Node(val);
         item->next = _dummyNode->next;
         _dummyNode->next = item;
         _size++;
     }
     
     void addAtTail(int val) {
         Node* item = new Node(val);
         Node* p = _dummyNode;
         while (p->next != NULL)
             p = p->next;
         p->next = item;
         _size++;
     }
     
     void addAtIndex(int index, int val) {
         if (index < 0 || index > _size)
             return;
         Node* item = new Node(val);
         Node* p = _dummyNode;
         for (int i = 0; i < index; i++)
             p = p->next;
         item->next = p->next;
         p->next = item;
         _size++;
     }
     
     void deleteAtIndex(int index) {
         if (index < 0 || index >= _size)
             return;
         Node* p = _dummyNode;
         for (int i = 0; i < index; i++)
             p = p->next;
         Node* item = p->next;
         p->next = item->next;
         delete item;
         _size--;
     }
 };
 ​
 /**
  * Your MyLinkedList object will be instantiated and called as such:
  * MyLinkedList* obj = new MyLinkedList();
  * int param_1 = obj->get(index);
  * obj->addAtHead(val);
  * obj->addAtTail(val);
  * obj->addAtIndex(index,val);
  * obj->deleteAtIndex(index);
  */

反转链表

题目思路:给定单链表的头结点 head,反转链表,并返回反转后的链表。

思路

首先创建一个带头节点的空链表,从前到后遍历原单链表,将该链表上的节点通过头插法插入空链表。

代码

1.迭代

 /**
  * Definition for singly-linked list.
  * struct ListNode {
  *     int val;
  *     ListNode *next;
  *     ListNode() : val(0), next(nullptr) {}
  *     ListNode(int x) : val(x), next(nullptr) {}
  *     ListNode(int x, ListNode *next) : val(x), next(next) {}
  * };
  */
 class Solution {
 public:
     ListNode* reverseList(ListNode* head) {
         if (head == NULL || head->next == NULL)
             return head;
         ListNode* dummyNode = new ListNode(-1);
         ListNode* p = head;
         ListNode* item; 
         while (p->next != NULL)
         {
             item = p->next;
             p->next = dummyNode->next;
             dummyNode->next = p;
             p = item;
         }
         // for last Node
         p->next = dummyNode->next;
         dummyNode->next = p;
         return dummyNode->next;
     }
 };

2.递归

 /**
  * Definition for singly-linked list.
  * struct ListNode {
  *     int val;
  *     ListNode *next;
  *     ListNode() : val(0), next(nullptr) {}
  *     ListNode(int x) : val(x), next(nullptr) {}
  *     ListNode(int x, ListNode *next) : val(x), next(next) {}
  * };
  */
 class Solution {
 public:
     ListNode* reverseList(ListNode* head) {
         if (head == NULL || head->next == NULL) // only one Node
             return head;
         ListNode* newHead = reverseList(head->next);
         ListNode* p = newHead;
         if (p != NULL)
         {
             while (p->next != NULL)
                 p = p->next;
         }    
         p->next = head;
         head->next = NULL;
         return newHead;
     } 
 };

下面这种比较巧妙,利用原节点head->next是head->next子链表的最后一个节点,从而不用遍历子链表即可把head连接在子链表的最后,从而反转整个链表。

 /**
  * Definition for singly-linked list.
  * struct ListNode {
  *     int val;
  *     ListNode *next;
  *     ListNode() : val(0), next(nullptr) {}
  *     ListNode(int x) : val(x), next(nullptr) {}
  *     ListNode(int x, ListNode *next) : val(x), next(next) {}
  * };
  */
 class Solution {
 public:
     ListNode* reverseList(ListNode* head) {
         if (head == NULL || head->next == NULL) // only one Node
             return head;
         ListNode* newHead = reverseList(head->next);
         head->next->next = head;  // head->next 原链表的第二个节点
         head->next = NULL;   
         return newHead;
     } 
 };