1.反转链表

解法思路:
将链表划分为俩部分; 将后半部分反转,然后与前部分对比,如果相同则为回文,否则不是
cpp
/**
* 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:
bool isPalindrome(ListNode* head) {
// 快慢指针划分容器,一分为二
// 定义快慢指针,相差位置1 ; 当快指针不为空且下一个位置不为空;则慢指针移动 1,快指针移动 2
// 慢指针所指位置就是划分点;
// 奇数长度时,慢指针指向的就是居中那个位置; 偶数时指向为第一位部分的右端点
// 根据上面方法将链表划分为俩部分; 将后半部分反转,然后与前部分对比,如果相同则为回文,否则不是
// 快慢指针
ListNode *slow = head, *fast = head->next;
while(fast && fast->next ){
slow = slow->next;
fast = fast->next->next;
}
// 从slow的下一个位置开始反转
ListNode *second = reverseList(slow->next);
// 将链表分割开
slow->next = NULL;
// 对比俩部分
ListNode *first = head;
while(second){ // 当第二部分指针不为空
if(first->val != second->val){
return false;
}
first = first->next;
second = second->next;
}
return true;
}
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr != nullptr) {
ListNode* nextTemp = curr->next; // 临时保存下一个节点
curr->next = prev; // 反转当前节点的指针
prev = curr; // 移动prev到当前节点
curr = nextTemp; // 移动curr到下一个节点
}
return prev; // prev现在是反转后链表的头节点
}
};
2.环形链表

解法思路:
// 快慢指针法,存在环,则因为指针速度不同,在寻找中,快指针一定会追上慢指针;
// 快慢指针出发点可以相同也可以不同
cpp
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
// 快慢指针法,存在环,则因为指针速度不同,在寻找中,快指针一定会追上慢指针;
// 快慢指针出发点可以相同也可以不同
if(head == nullptr ||head->next == nullptr ){
return false;
}
ListNode *slow = head, *fast = head->next;
while (slow != fast) {
if (fast == nullptr || fast->next == nullptr) {
return false;
}
slow = slow->next;
fast = fast->next->next;
}
return true;
}
};
快慢指针总结:
快慢指针算法广泛用于线性表操作,通常让快慢指针(同一位置/相差1位置)开始移动。
慢指针每次移动一步。
快指针每次移动两步。
举例:
链表划分为两个相等的部分,:
- 让快指针和慢指针都从链表的头部开始。
- 慢指针每次移动一步。
- 快指针每次移动两步。
- 当快指针到达链表末尾时(或者快指针的下一个节点为空时,意味着链表长度为奇数,快指针已经走过了中点),慢指针将位于链表的中点附近。
- 此时,以慢指针所在的位置为分界点,将链表划分为两部分。
检测链表中是否存在环
- 慢指针每次移动一步。
- 快指针每次移动两步。
当链表中存在环时,由于快指针相对于慢指针的速度优势,它们最终会在环内的某个位置相遇。