有时候处理链表相关问题的时候,定义“快指针”和“慢指针“的方法有时候会极大地提高时间效率。下面是常见的几种使用这个方法的情况。假设不考虑异常输入的情况。
判断一个链表是否有环
定义两个指针,快指针步长为2,慢指针步长为1.同时从链表头开始出发。如果链表中有环那么他们必然相遇。
1 bool hasCycle(ListNode *head) { 2 if(!head) 3 return false; 4 ListNode* fast = head->next; 5 ListNode* slow = head; 6 while(fast) { 7 if(fast == slow) 8 return true; 9 if(fast->next&&fast->next->next){ 10 fast = fast->next->next; 11 slow = slow->next; 12 } 13 else 14 return false; 15 } 16 return false; 17 }
求链表中倒数第k个结点
假设链表长度为n,那么我们轻松得出这些结论:链表中的倒数第k个结点也就是正数第n-(k-1)个结点。所以我们只需要正向的让指针走n-k次,那么指针停留的结点便是倒数第k个结点。走完这个链表需要走的步长是n-1。
我们定义两个指针,快指针先出发,走k-1步。此时它停在正数第k个结点上。慢指针也开始从链表头出发。两个指针步长都为1,走到快指针为NULL为止。快指针停止时他走的第二段路的长度就是慢指针的长度:(n-1)-(k-1)= n-k.根据第一段的推导可知此致慢指针的指向便是倒数第k个结点。
1 ListNode* find(ListNode* head,int k) 2 { 3 if(!head) 4 return NULL; 5 ListNode* fast = head; 6 ListNode* slow = head; 7 for(int i=0;i<k-1;++) 8 fast = fast->next; 9 while(fast) 10 { 11 fast = fast->next; 12 slow = slow->next; 13 } 14 return slow; 15 }
求链表的中间结点
这个比较简单。也是定义两个指针,快指针步长为2,慢指针步长为1。同时从head出发,当快指针为NULL时,慢指针就停在中间结点了。
1 ListNode* findMid(ListNode* head) 2 { 3 if(!head) 4 return NULL; 5 ListNode* fast = head; 6 ListNode* slow = head; 7 while(fast = fast->next) 8 { 9 fast = fast->next; 10 slow = slow->next; 11 } 12 return slow; 13 }
时间: 2024-10-14 01:45:17