1. 203移除链表元素
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
- 注意点
- 如果头结点就是要删除的元素,应该怎么写
- 注意使用 ListNode和ListNode * 遍历的区别
/**
* 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 *vir = new ListNode(0);
vir->next = head;
ListNode *temp = vir;
while(temp->next != nullptr){
if(temp->next->val == val){
// 这里要记得删除等于val的节点
ListNode *temNode = temp->next;
temp->next = temp->next->next;
delete temNode;
}else{
// 如果不相等这个指针后移动, 这里如果不使用指针的话,不好操作 tem是ListNode, 而next是 *ListNode
temp = temp->next;
}
}
return vir->next;
}
};
2.设计链表
class MyLinkedList {
public:
// 1. ListNode的构造函数后面不加;
// 2. struct完后需呀加;
struct LinkedNode{
int val;
LinkedNode* next;
LinkedNode(int val): val(val), next(nullptr){}
};
MyLinkedList() {
virNode = new LinkedNode(0);
_size = 0;
}
int get(int index) {
if (index > (_size - 1) || index < 0) {
return -1;
}
LinkedNode* cur = virNode->next;
while(index--){ // 如果--index 就会陷入死循环
cur = cur->next;
}
return cur->val;
}
void addAtHead(int val) {
// new ListNode只能赋值给指针
LinkedNode* newHead = new LinkedNode(val);
// ListNode* newHead(val); // 这么做会报错
newHead->next = virNode->next;
virNode->next = newHead;
_size++;
}
void addAtTail(int val) {
// ListNode* newTail(val);
LinkedNode* newTail = new LinkedNode(val);
LinkedNode* tempNode = virNode;
while(tempNode->next != nullptr){
tempNode = tempNode->next;
}
tempNode->next = newTail;
_size++;
}
void addAtIndex(int index, int val) {
// 注意这里是下标为index的节点之前, 这里节点下标从0开始
if(index > _size){
return ;
}
if(index < 0) index = 0;
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* curNode = virNode;
while(index--){
curNode = curNode->next;
}
newNode->next = curNode->next;
curNode->next = newNode;
_size++;
}
void deleteAtIndex(int index) {
// if(index >= _size-1 || index < 0){
if(index >= _size || index < 0){ // 这里应该是 >= size
return;
}
LinkedNode* curNode = virNode;
while(index--){
curNode = curNode->next;
}
LinkedNode* temNode = curNode->next;
curNode->next = curNode->next->next;
delete temNode;
_size--;
}
private:
int _size;
LinkedNode* virNode;
};
/**
* 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);
*/
3.翻转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
- 非递归写法
- 注意这里开始操作的节点是虚拟头结点和头结点,方便翻转后判断是否到结尾
ListNode* reverseList(ListNode* head) {
// 非递归法
ListNode *tem; // 暂存下一个节点
ListNode *first = nullptr;
ListNode *second = head;
while(second){
tem = second->next;
second->next = first;
first = second;
second = tem;
}
return first;
}
- 递归写法
- 这里的递归要注意如何返回新的头结点
class Solution {
public:
ListNode* reverse(ListNode* per, ListNode* cur){
if(cur == nullptr){
return per;
}
ListNode *tem = cur->next;
cur->next = per;
return reverse(cur, tem);
}
ListNode* reverseList(ListNode* head) {
if(head == nullptr){
return head;
}
ListNode* virHead = nullptr;
ListNode* newHead = reverse(virHead, head);
return newHead;
}
};
- 需要让head->next 每次都指向空,否则最后一个节点会和倒数第二个节点互相指,无限循环输出
- 再考虑为什么reverList要卸载 head的操作之前
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head == nullptr || head->next == nullptr){
return head;
}
ListNode *last = reverseList(head->next);
head->next->next = head;
head->next = nullptr; // 如果不指向空,最后一个节点会和倒数第二个节点互相指
return last;
}
};