两两交换链表中的节点
题目解答(增加了一些部分,方便编译器运行)
#include<iostream>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x): val(x), next(nullptr){}
};
class Solution {
public:
static ListNode* swapPairs(ListNode* head) {
if (head == nullptr || head->next == nullptr) return head;
ListNode* Head = new ListNode(0);
Head->next = head;
ListNode* p1 = Head, *p2 = head, *p3 = head->next, *p4 = head->next->next;
while (p2 != NULL && p3 != NULL) {
p1->next = p3;
p3->next = p2;
p2->next = p4;
if (!p2) break;
else p1 = p2;
if (!p1->next) break;
else p2 = p1->next;
if (!p2->next) break;
else p3 = p2->next;
p4 = p3->next;
}
head = Head->next;
delete Head;
return head;
}
};
int main() {
//输入
int num;
cin >> num;
ListNode* head = new ListNode(num);
ListNode* point = head;
while (cin.get() != '\n') {
cin >> num;
point->next = new ListNode(num);
point = point->next;
}
head = Solution::swapPairs(head);
//输出
while (head) {
if (head->next == nullptr) {
cout << head->val << " -> NULL";
}
else {
cout << head->val << " -> ";
}
head = head->next;
}
return 0;
}
解题心得
1、处理两个节点,同样要拿到这两个节点的前后节点。
删除链表中的倒数第N个节点
题目解答(增加了一些部分,方便编译器运行)
#include<iostream>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
class Solution {
public:
static ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* Head = new ListNode(0);
Head->next = head;
ListNode* point = head;
int count = 0;
while (count++ < n) {
point = point->next;
if (!point) break;
}
if (!point && count != n) return NULL;
ListNode* point2 = Head;
while (point) {
point = point->next;
point2 = point2->next;
}
ListNode* temp = point2->next;
point2->next = temp->next;
delete temp;
head = Head->next;
delete Head;
return head;
}
};
int main() {
//输入
int num;
cin >> num;
ListNode* head = new ListNode(num);
ListNode* point = head;
while (cin.get() != '\n') {
cin >> num;
point->next = new ListNode(num);
point = point->next;
}
int n;
cin >> n;
head = Solution::removeNthFromEnd(head, n);
//输出
while (head) {
if (head->next == nullptr) {
cout << head->val << " -> NULL";
}
else {
cout << head->val << " -> ";
}
head = head->next;
}
return 0;
}
解题心得
1、该题目运用双指针的快慢指针的方法,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。
链表相交
题目解答
/**
* 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) {
ListNode* curA=headA;
ListNode* curB=headB;
int lenA=0, lenB=0;
while(curA){
curA=curA->next;
lenA++;
}
while(curB){
curB=curB->next;
lenB++;
}
curA=headA, curB=headB;
if(lenB > lenA){
swap(lenA, lenB);
swap(curA, curB);
}
int len=lenA-lenB;
while(len-- && curA){
curA=curA->next;
}
while(curA && curB){
if(curA == curB) return curA;
curA=curA->next;
curB=curB->next;
}
return NULL;
}
};
解题心得
该题目同样运用快慢指针的方法,先找出较长的链表,然后先让长链表的指针先跑一个差值,再让长链表的指针和断链表的从起始位置的指针同时跑,同时每跑一次比较两个结点是否一样,一样就返回该值;最后不一样就返回空。
环形链表II
题目解答
/**
* 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* fast=head, * slow=head;
while(fast!=NULL && fast->next !=NULL){
slow=slow->next;
fast=fast->next->next;
if(slow==fast){
ListNode* node1=head;
ListNode* node2=fast;
while(node1 != node2){
node1=node1->next;
node2=node2->next;
}
return node1;
}
}
return nullptr;
}
};
解题心得
题目真的很难,感觉,还要运用到算法知识,所以,就直接看卡子哥的题解了。
该题目要判断链表是否环如果有环,而且如何找到这个环的入口。
1.如何判断是否有环,运用快慢指针,fast每次动两位,slow每次动一位,如果fast能追到slow(相对运动),那么一定会是有环的。
2.如何找到入口,定义两个指针,一个从链表的头结点出发,一个从快慢指针的相遇节点出发,让两个指针同时出发,两指针相遇的结点就是环的入口。