1.题目:给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
## 虚拟头结点还是很舒服的,直接统一操作无需单独考虑头结点,另外需考虑用delete删除不要结点的空间
/**
* 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) {}
* };
*/
## 总结:1:生成虚拟头结点并用ListNode*cur记录当前结点 2:设置临时ListNode* temp用来删除结点 3:修改cur的next
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* cur = dummyHead;
while(cur->next != NULL){
if(cur->next->val == val){
ListNode* temp = cur-> next;
cur->next = cur->next->next;
delete temp;
}
else{
cur = cur->next;
}
}
head = dummyHead->next;
delete dummyHead;
return head;
}
};
2. 题目:
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:val
和 next
。val
是当前节点的值,next
是指向下一个节点的指针/引用。
如果是双向链表,则还需要属性 prev
以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。
实现 MyLinkedList
类:
MyLinkedList()
初始化MyLinkedList
对象。int get(int index)
获取链表中下标为index
的节点的值。如果下标无效,则返回-1
。void addAtHead(int val)
将一个值为val
的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。void addAtTail(int val)
将一个值为val
的节点追加到链表中作为链表的最后一个元素。void addAtIndex(int index, int val)
将一个值为val
的节点插入到链表中下标为index
的节点之前。如果index
等于链表的长度,那么该节点会被追加到链表的末尾。如果index
比长度更大,该节点将 不会插入 到链表中。void deleteAtIndex(int index)
如果下标有效,则删除链表中下标为index
的节点。
## 注意这里需要进行私有成员变量的声明,以及需要自己创建数据结构,并包装在mylinkedlist类中
class MyLinkedList {
public:
struct LinkNode{
int val;
LinkNode* next;
LinkNode(int x): val(x), next(nullptr){}
};
MyLinkedList(): _dummyhead(new LinkNode(0)), _size(0){}
int get(int index) {
if (index > (_size - 1) || index < 0){
return -1;
}
LinkNode* cur = _dummyhead->next;
while(index--){
cur = cur->next;
}
return cur->val;
// MyLinkedList* p = head;
// int count = 0;
// while(!p){
// if(count == index ){
// return p->val;
// }
// count++;
// }
// return -1;
}
void addAtHead(int val) {
LinkNode* newhead = new LinkNode(val);
newhead->next = _dummyhead->next;
_dummyhead->next = newhead;
_size++;
}
void addAtTail(int val) {
LinkNode* newtail = new LinkNode(val);
LinkNode* cur = _dummyhead;
while(cur->next != nullptr){
cur = cur->next;
}
cur ->next = newtail;
_size++;
}
void addAtIndex(int index, int val) {
if(index > _size) return;
if(index < 0) index = 0;
LinkNode* newNode = new LinkNode(val);
LinkNode* cur = _dummyhead;
while(index--){
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
_size++;
// MyLinkedList* p = new MyLinkedList(val);
// MyLinkedList* cur = head;
// MyLinkedList* temp;
// int count = 0;
// if(head == nullptr){
// if (index > count){
// }
// }
// else{
// while(!cur){
// temp = cur;
// cur = cur->next;
// count++;
// }
// }
}
void deleteAtIndex(int index) {
if (index >= _size || index < 0){
return;
}
LinkNode* cur = _dummyhead;
while(index--){
cur = cur->next;
}
LinkNode* temp = cur ->next;
cur->next = cur->next->next;
delete temp;
temp = nullptr;
_size--;
}
private:
LinkNode* _dummyhead;
int _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);
*/
3. 题目:给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
## 本题简单一些,只需两个指针即可,易于理解。对于翻转时只需用while(cur)即可,无需虚拟头结点。
/**
* 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) {
ListNode* temp;
ListNode* cur = head;
ListNode* pre = NULL;
while(cur){
temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
};
总结:(1)链表翻转无需虚拟结点,直接while(cur)即可,循环里面是双指针逻辑
(2)链表删除指定元素,建议使用虚拟头结点,while(cur->next != Null)直接判断val值
(3)链表设计中寻找某个下标元素时用while(index--)即可找到对应位置,是否需要虚拟头结点自行判断,以后总结。