O(1)
,查询的复杂度为0(n)
,和数组刚好相反链表的定以结构如下:
struct ListNode{
int val;
ListNode *next;
ListNode(int x):val(x), next(nullptr){}
题目链接:移除链表元素
移除链表元素看起来是很简单的,但是写起来比较难以思考。首先有一点:删除头结点和中间的节点是不一样的(因为头结点没有前一个元素)。所以要对头结点和其他节点单独处理。第二点:删除元素时不能让cur
指在要删除的元素上,要指在它的上一个元素,因为你要让cur->next = cur->next->next
,如果指在了要删除的元素上,则无法找到它的上一个元素。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
//
while(head != nullptr && head->val == val){
ListNode *delNode = head;
head = head->next;
delete delNode;
}
ListNode *cur = head;
while(cur!=nullptr && cur->next != nullptr){
if(cur->next->val == val){
ListNode *delNode = cur->next;
cur->next = cur->next->next;
delete delNode;
}
else{
cur = cur->next;
}
}
return head;
}
};
使用虚拟头结点
的方法则可以将头节点和其余节点一起进行处理,不用再区分是不是头结点,是一个很好的方法。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummyNode = new ListNode();
dummyNode->next = head;
ListNode* cur = dummyNode;
while(cur->next!=nullptr){
if(cur->next->val == val){
ListNode* delNode = cur->next;
cur->next = cur->next->next;
delete delNode;
}
else{
cur = cur->next;
}
}
return dummyNode->next;
}
};
题目链接:设计链表
设计链表,首先要定义链表的节点,然后一个链表应该有一个头指针(作为哨兵,也就是虚拟头指针,并不计入链表的元素数量,也就是这个指针并不是链表中的元素)和记录链表中元素多少的变量size
。size
是链表中元素的个数,而不是下标的最大值。
之前我总想着的是把这个哨兵指针当成链表中的元素,导致代码出错。
class MyLinkedList {
public:
struct ListNode
{
int val;
ListNode* next;
ListNode(int x):val(x),next(nullptr){}
};
MyLinkedList() {
dummpyHead = new ListNode(0);
size = 0;
}
int get(int index) {
if(index >= size){
return -1;
}
ListNode *cur = dummpyHead->next;
while(index--){
cur=cur->next;
}
return cur->val;
}
void addAtHead(int val) {
ListNode *insertNode = new ListNode(val);
insertNode->next = dummpyHead->next;
dummpyHead->next = insertNode;
size++;
}
void addAtTail(int val) {
ListNode *insertNode = new ListNode(val);
ListNode *cur = dummpyHead;
while(cur->next != nullptr){
cur = cur->next;
}
cur->next = insertNode;
size++;
}
void addAtIndex(int index, int val) {
if(index>size){
return;
}
ListNode *insertNode = new ListNode(val);
ListNode *cur = dummpyHead;
while(index--){
cur = cur->next;
}
insertNode->next = cur->next;
cur->next = insertNode;
size++;
}
void deleteAtIndex(int index) {
if(index >= size){
return;
}
ListNode *cur = dummpyHead;
while(index--){
cur = cur->next;
}
cur->next = cur->next->next;
size--;
}
private:
ListNode* dummpyHead;
int size;
};
题目链接:翻转链表
乍一看,,因为数组的思想已经根深蒂固,想着把链表中的元素给翻转过来。然后。。。。。。就没有然后了。感觉自己的思维很混乱。
看了题解以及视频,才明白使用双指针法两个两个的改变链表中next
的朝向。没有想到这一点,但是想到了要改变next
的朝向,使用双指针两两改变。太厉害了,真的是太厉害了。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *cur = head;
ListNode *pre = nullptr;
while(cur != nullptr){
ListNode *tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
};