上次我们在双指针部分介绍了一部分链表的题目。
【从零开始】双指针的配合
其实链表的大部分题目确实与双指针有关。而这次我们再补充一些题目,顺便使用一个非常好用的链表技巧:虚头节点
设计链表
这是一道综合性的题目,把所有链表的基本操作都包括了。
主要实现以下功能:
- 获取第index个节点的值
- 在链表第一个元素之前添加一个val
- 在链表的最后一个元素之后添加一个val
- 在链表第index个节点之前添加一个val
- 删除第index个节点
要注意index是从0开始的、
虚头节点dummy head
在添加和删除时,如果这个元素是头节点,或者需要添加在头节点之前,那么我们就需要对头节点单独写一段代码处理。
为了省去这个步骤,我们可以设定虚头节点来作为临时的头节点,这样在处理真正的head时就与后面的节点操作无异了。
ListNode *dummy_head=new listNode(0);
dummy_head->next=head;
从链表结构体开始
其实我们在leetcode中经常使用链表,却非常容易忽视链表结构体的写法
struct LinkedNode{
int val;
LinkedNode* next;
LinkedNode(int val):val(val),next(NULL){}
};
基础链表由val值和指向下一个节点的next构成。
构建MyLinkedList
class MyLinkedList{
private:
LinkedNode *dummyHead;
int size;
public:
MylinkedList(){
dummyHead=new LinkedNode(0);
size=0;
}
}
构造一个虚头节点dummtHead和链表的长度size。
获取index节点
因为index从0开始,如果我们要第3个,那么是从0,1,2,3走的,实际经过4个节点。
这时要从dummyHead的下一个真正的头节点开始遍历:
int get(int index) {
if(index<0||index>size-1){
return -1;
}
LinkedNode *cur=dummyHead->next;
while(index){
cur=cur->next;
index--;
}
return cur->val;
}
在链表头添加val
在链表头添加值为val的节点,其实是在虚头节点之后添加(这时候就体现出虚头节点的好处)
void addAtHead(int val) {
LinkedNode *node=new LinkedNode(val);
node->next=dummyHead->next;
dummyHead->next=node;
}c
创建新节点后,剩下的工作就是穿针引线