1. what is linked list
链表,线性表的一种
2. linked list structure
常见的链表结构有:
- singly linked list 单链表
- doubly linked list 双向链表
- circularly linked 循环链表
3. 链表成环的相关问题
3.1通常判断链表成环的思路有:
①是利用追及问题的思想,由一快一慢的2个指针追及来判断是否成环。
②记录遍历过程中每一个节点,查看当前遍历到的是否之前已经访问过了。
3.2寻找cycle入口结点思路:
法①(比较好想,但是效率不太高)
使用哈希表来存储访问过的在遍历链表的时候看看是否有某个节点曾经访问过
法②(效率比较高,可以让时间复杂度保持在O(N),空间复杂度O(1))
假设环外长度设为 a,环的起点为x1,一快一慢两个指针相遇时的地点在x1前方距离为c的某个节点。
那么第一次相遇时slow指针走过的距离:a+c,fast指针走过的距离:a+c+未知距离(从x1开始、结束于环的起点,可能已经走了很多圈,也有可能一圈还没走完+c。
因为fast的速度是slow的两倍,所以fast走的距离是slow的两倍,所以 未知距离=a !!!
因此:
如果一个指针从链表的起点出发,另外一个从x1出发,且他们速度相同,他们一定会相遇在环的起点!!!
/*leetcode 142. Linked List Cycle II */
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if (head == NULL|| head->next ==NULL)
return NULL;
ListNode *slow= head;
ListNode *fast= head;
while (fast != NULL && fast->next != NULL)
{ //fast 是 slow 速度的2倍
slow =slow->next;
fast =fast->next->next;
//如果他们相遇了,证明环已经存在,现在进行第二步:在起点和相遇点放置速度相同的指针
//他们一定会相遇在环的起点!
if (slow == fast)
{
slow = head;
while (slow != fast)
{
slow = slow->next;
fast =fast->next;
}
return slow;
}
}
return NULL;
}
};
使用哈希表来实现如下(将节点的地址保存到哈希表中)
class Solution {
public:
ListNode *detectCycle(ListNode *head)
{
unordered_set<int>visited;
if (head == NULL|| head->next ==NULL)
return NULL;
ListNode *pointer=head;
while (pointer->next !=NULL)
{
if(visited.count(long(pointer)))
return pointer;
visited.insert(long(pointer));
pointer=pointer->next;
}
return NULL;
}
};
3.3 反转链表
//遍历整个链表,用temp保存当前遍历的节点,每走一步将两个节点之间的指针反转
class Solution
{
public:
ListNode* reverseList(ListNode* head)
{
ListNode*pt=head;
ListNode*temp;
if(pt==NULL) return head;
while(pt->next!=NULL)
{
temp=pt->next; //temp 在当前节点往前走一位
pt->next=pt->next->next; //当前节点指向前面第二个人
temp->next=head; //前面第一个节点指向当前节点
head=temp; //head为当前节点前面前面一个节点
}
return head;
}
};