目录
141. 环形链表
问题描述:
实现代码与解析:
快慢指针:
原理思路:
142. 环形链表 II
问题描述:
实现代码与解析:
快慢指针
原理思路:
143. 重排链表
题目描述:
实现代码与解析:
线性表
原理思路:
141. 环形链表
问题描述:
给你一个链表的头节点 head
,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true
。 否则,返回 false
。
示例 1:
输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0 输出:true 解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1 输出:false 解释:链表中没有环。
实现代码与解析:
快慢指针:
/*** 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) {ListNode* slow = head;ListNode* fast = head;// fast->next 这个条件,防止fast为空结点while(slow && fast && fast->next){fast = fast->next->next;slow = slow->next;if (fast == slow) return true;}return false;}
};
原理思路:
慢指针一次走一步,快指针一次走两步,若最后能相遇说明有环。
142. 环形链表 II
问题描述:
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1 输出:返回索引为 1 的链表节点 解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0 输出:返回索引为 0 的链表节点 解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1 输出:返回 null 解释:链表中没有环。
实现代码与解析:
快慢指针
/*** 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;//快指针ListNode* slow=head;//慢指针while(fast!=NULL&&fast->next!=NULL){slow=slow->next;//慢指针每次走一步fast=fast->next->next;//快指针每次走两步if(slow==fast){ListNode* index1=fast;//记录相遇位置ListNode* index2=head;//当快慢指针相遇时,两指针从head和相遇点同时出发,直至相遇,找到换的入口while(index1!=index2){index1=index1->next;index2=index2->next;}return index1;}}return NULL;//若无环}
};
原理思路:
slow指针一次走一步,fast指针一次走两步。
其中n为fast指针在圈里转的圈数,根据算的结果可以看出,当n=1时,z=x,也就是说fast与slow相遇点到环的入口的长度等于x的长度,所以我们只要在头结点和相遇点定义index1,index2两个指针,一起移动,当其相遇的时候,就移动到了环的入口结点,直接返回即可。当然n不一定等于1,根据最后公式,只不过index2会在环里转几圈,最后还是会与index1在环入口相遇。
至于fast指针与slow指针为什么一定会相遇,而不是fast指针跳过slow指针呢?因为fast指针相对于slow指针一次是走一步,相当于物理里的相对运动吧,既然是走一步,那必然不会出现跳过的情况。
至于为什么slow指针不会在环里转超过一圈呢?因为fast指针一次走的是slow指针一次走的两倍,当slow走完一圈时,fast必然会走完两圈,所以在此之前两指针一定会相遇。
143. 重排链表
题目描述:
给定一个单链表 L
的头节点 head
,单链表 L
表示为:
L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入:head = [1,2,3,4] 输出:[1,4,2,3]
示例 2:
输入:head = [1,2,3,4,5] 输出:[1,5,2,4,3]
实现代码与解析:
线性表
/*** 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:void reorderList(ListNode* head) {ListNode* cur = head;vector<ListNode*> v;while(cur){v.push_back(cur);cur = cur->next;}int l = 0, r = v.size() - 1;while(l < r){v[l]->next = v[r];l++;if (l == r) break;v[r]->next = v[l];r--;}v[l]->next = nullptr;//重排后的链表,最后一个节点是原来链表中间的节点,其next不为空,我们需要手动将next设为空。}
};
原理思路:
链表不能记录位置,我们用线性表存一下进行操作即可。