题目链接:leecode206.反转链表
第一种方法:双指针
刚开始有点头铁,不知道下面这个方法的错误在哪里。最后充了会员调试后才看出来问题在哪里。
/**
* 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) {
// if(head->next == nullptr) return head;
// if(head == nullptr) return nullptr;
ListNode* tmp_cur;
//你可能觉得这样写是对的,但是这里有一个致命的错误,
//就是链表可能出现闭环,因为一般链表的最后一个元素
//的next指向nullptr,但是试想,如果这么写,pre指针
//并没有初始化pre->next = nullptr,而是pre->next=cur
//但是经过反转,cur->next = pre。这样的链表反复横
//跳,形成闭环!!!
ListNode* cur = head->next;
ListNode* pre = head;
while(cur != nullptr){
tmp_cur = cur->next;
cur->next = pre;
pre = cur;
cur = tmp_cur;
}
return pre;
}
};
所以正确的写法应该是:
/**
* 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) {
//记住这里的顺序不能反过来哦
if(head == nullptr) return nullptr;
if(head->next == nullptr) return head;
ListNode* tmp_cur;
ListNode* cur = head;
ListNode* pre = nullptr;
while(cur != nullptr){
tmp_cur = cur->next;
cur->next = pre;
pre = cur;
cur = tmp_cur;
}
return pre;
}
};
第二种方法:递归写法,这种写法也很好哦
/**
* 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* current = head;
ListNode* previous = nullptr;
return reverse(previous, current);
}
ListNode* reverse(ListNode* previous, ListNode* current){
if(current == nullptr) return previous;
ListNode* tmp = current->next;
current->next = previous;
previous = current;
current = tmp;
return reverse(previous, current);
}
};
题目链接:leecode24.两两交换
下面这个写法是错的
/**
* 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* dummyNode = new ListNode(0);
dummyNode->next = head;
ListNode* current = dummyNode;
while(current!=nullptr && current->next!=nullptr && current->next->next!=nullptr){
ListNode* Cur_tmp = current->next;
ListNode* Late_tmp = current->next->next;
//这里虽然没有出错,但是也要避免使用。
current->next = Cur_tmp->next;
current->next->next = Cur_tmp;
//错误就出现在这里,late_tmp本来等于current->next->next,
//但是在上一步current->next->next已经被改变了
//这就会导致循环链表
current->next->next->next= Late_tmp->next;
current = current->next->next;
}
return dummyNode->next;
}
};
下面才是正确的写法
/**
* 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* dummyNode = new ListNode(0);
dummyNode->next = head;
ListNode* current = dummyNode;
while(current!=nullptr && current->next!=nullptr && current->next->next!=nullptr){
ListNode* Cur_tmp = current->next;
ListNode* Late_tmp = current->next->next->next;
current->next = current->next->next;
current->next->next = Cur_tmp;
current->next->next->next= Late_tmp;
current = current->next->next;
}
return dummyNode->next;
}
};
题目链接leecode19.删除链表的倒数第 N 个结点
这道题一共有两种写法,先写朴素版写法
/**
* 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* dummyNode = new ListNode(0);
dummyNode->next = head;
ListNode* cur = dummyNode;
int size = 0;
while(cur!=nullptr && cur->next!=nullptr){
cur = cur->next;
size++;
}
//删除倒数第n个,等于删除正数第size-n后面的点
if(size >= n){
int index = size - n;
cur = dummyNode;
while(cur!=nullptr && cur->next!=nullptr && index>0){
cur = cur->next;
index--;
}
//现在就是删除current后面的点
ListNode* tmp = cur->next;
cur->next = tmp->next;
delete tmp;
}
return dummyNode->next;
}
};
上面的写法一共把链表扫了两边,但是如果用双指针或者快慢指针算法,就可以只扫一遍链表!那就是快慢指针的写法。
/**
* 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* dummyNode = new ListNode(0);
dummyNode->next = head;
ListNode* fast = dummyNode;
ListNode* slow = dummyNode;
while(n > 0){
fast = fast->next;
n--;
}
while(fast!=nullptr && fast->next!=nullptr){
fast = fast->next;
slow = slow->next;
}
ListNode* tmp = slow->next;
slow->next = tmp->next;
delete tmp;
return dummyNode->next;
}
};
让快指针先走n步,当快指针走到底的时候,要删除的点就是slow指针后面的那个。