代码随想录算法训练营|链表内容复习
链表内容复习
移除链表元素
分别删除目标值结点
点击查看代码
/**
* 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) {
while (head != NULL && head->val == val) {
ListNode* tmp = head;
head = tmp->next;
delete tmp;
}
ListNode* cur = head;
while (cur != NULL && cur->next != NULL) {
if (cur->next->val == val) {
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
} else {
cur = cur->next;
}
}
return 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) {
ListNode* dummyHead = new ListNode(0);
ListNode* cur;
dummyHead->next = head;
cur = dummyHead;
while (cur != NULL && cur->next != NULL) {
if (cur->next->val == val) {
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
} else {
cur = cur->next;
}
}
return dummyHead->next;
}
};
设计链表
707. 设计链表 707的代码之前的竟然通过不了了Σ(っ °Д °;)っ,我需要找一下原因
首先是错误原因找到了,deleteAtIndex函数的条件判断中,错误写成了if (index >= size - 1 || index < 0) return;,应该是if (index > size - 1 || index < 0) return;
这次对原文档中的错误进行了修正,补充了一些小错误的解决思路,这次发现对链表的实现又多了写些领悟
点击查看代码
class MyLinkedList {
public:
struct LinkNode {
int val;
LinkNode* next;
LinkNode(int val):val(val), next(NULL){}
};
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;
}
void addAtHead(int val) {
LinkNode* newNode = new LinkNode(0);
newNode->val = val;
LinkNode* cur = dummyHead;
newNode->next = cur->next;
cur->next = newNode;
size++;
}
void addAtTail(int val) {
LinkNode* cur = dummyHead;
while(cur->next != NULL) {
cur = cur->next;
}
LinkNode* tail = new LinkNode(0);
tail->val = val;
cur->next = tail;
size++;
}
void addAtIndex(int index, int val) {
LinkNode* cur = dummyHead;
if (index > size) return;
while (index--) {
cur = cur->next;
}
LinkNode* pre = new LinkNode(0);
pre->val = val;
LinkNode* next = cur->next;
cur->next = pre;
pre->next = next;
size++;
}
void deleteAtIndex(int index) {
if (index > size - 1 || index < 0) return;
LinkNode* cur = dummyHead;
while (index--) {
cur = cur->next;
}
LinkNode* tmp = cur->next;
cur->next = tmp->next;
delete tmp;
size--;
}
private:
int size;
LinkNode* dummyHead;
};
/**
* 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);
*/
今天又把707写了一遍,又是报错没有找出来,最后发现是get函数写错了。在get函数中,cur的指向是LinkNode* cur = dummyHead->next;,dummyHead是虚拟头结点,其下一个结点才指向的是第一个结点,我说怎么所有结点前面多了一个0呢
反转链表
206. 反转链表 反转链表的题目用双指针很简单,注意最后返回的是pre指针而不再是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) {
ListNode* cur = head;
ListNode* pre = NULL;
ListNode* tmp;
while (cur != NULL) {
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
};
两两交换链表中的节点
感觉这个链表题的套路性比较强,按照之前的做法来一遍确实可以避免跟多问题。之前写的这个用的一个right指针指向了left->next,但是没有用虚拟头结点,这样一来,遇到[1,2,3,4]的时候,只能执行一遍,就没有办法翻转后面的[3,4]
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if (head == NULL || head->next == NULL) return head;
ListNode* left = head;
ListNode* right = left->next;
cout << left->next->val << right->next->next->val << endl;
while (left->next != NULL && left->next->next != NULL) {
// cout << left->val << right->val << endl;
int tmp = left->val;
left->val = right->val;
right->val = tmp;
left = left->next->next;
right = left->next;
// cout << left->next->val << endl;
}
return 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* swapPairs(ListNode* head) {
if (head == NULL || head->next == NULL) return head;
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* left = dummyHead;
ListNode* right = left->next;
// cout << left->next->val << right->next->next->val << endl;
while (left->next != NULL && left->next->next != NULL) {
// cout << left->val << right->val << endl;
int tmp = left->next->val;
left->next->val = right->next->val;
right->next->val = tmp;
left = left->next->next;
right = left->next;
// cout << left->next->val << endl;
}
return dummyHead->next;
}
};
另外就是正常的之前写的k哥版代码如下,这种是直接定义了中间的链表指针来进行交换
点击查看代码
/**
* 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* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* cur = dummyHead;
ListNode* tmp;
ListNode* tmp1;
while (cur->next != NULL && cur->next->next != NULL) {
tmp = cur->next;
tmp1 = cur->next->next->next;
cur->next = tmp->next;
cur->next->next = tmp;
cur->next->next->next = tmp1;
cur = cur->next->next;
}
return dummyHead->next;
}
};
删除链表的倒数第 N 个结点
19. 删除链表的倒数第 N 个结点 看了下之前的思路,还是很巧的,用的是双指针,不过这次用的循环条件成了while (right->next != NULL)和之前意思一样
点击查看代码
/**
* 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* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* left = dummyHead;
ListNode* right = dummyHead;
while (n--) {
right = right->next;
}
while (right->next != NULL) {
left = left->next;
right = right->next;
}
ListNode* tmp;
tmp = left->next;
left->next = tmp->next;
delete tmp;
return dummyHead->next;
}
};
链表相交
面试题 02.07. 链表相交 这个题思路没有什么难的,写几遍基本就不会错了,代码实现很简单
点击查看代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int len1 = 0;
int len2 = 0;
ListNode* curA = headA;
ListNode* curB = headB;
while (curA != NULL) {
curA = curA->next;
len1++;
}
while (curB != NULL) {
curB = curB->next;
len2++;
}
int len;
if (len1 > len2) len = len1 - len2;
else {
swap(headA, headB);
len = len2 - len1;
}
curA = headA;
curB = headB;
// cout << len2 << len1 << endl;
while (len--) {
curA = curA->next;
}
while (curA != NULL && curB != NULL) {
if (curA == curB) return curA;
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
环形链表Ⅱ
142.环形链表II 这道题是有两个问题,首先第一个是是否有环,第二个是要得出环的入口。首先可以在草稿纸上画出那个环,之后这道题的核心就是\(x\)的距离等于\(n-1\)圈加上\(z\)的距离,代入\(n=1\)之后,得到\(x=z\)
逻辑搞明白了,代码就十分简单了
点击查看代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
// 首先判断是否有环
ListNode* slow = head;
ListNode* fast = head;
while (fast != NULL && fast->next != NULL) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
ListNode* index = fast;
ListNode* index2 = head;
while (index2 != index) {
index = index->next;
index2 = index2->next;
}
return index;
}
}
return NULL;
}
};
链表完结🌺🌺
浙公网安备 33010602011771号