测试地址
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if( head == NULL || head->next == NULL )
return head;
else{
ListNode *new_head = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return new_head;
}
}
};
是否有环:
申请两个指针一个每一次走两步,另一个每一次走一步,如果快指针的next为null,则表明没有环。
环的入口:
如图所示,快慢指针在距离环起点w的位置相遇,那说明快指针比慢指针多走了几个环(设为kn,n表示环的长度,k=1、2、3……),假设一共走了x步才相遇,那可以得到如下的公式:
2x = x + k*n (k=1、2、3……)
有以上公式看到相遇点走的步数一定是环长度的k倍才可以相遇,即:
x = k*n;
还可以知道:
x = t + w
由此可以推到:
k*n = t + w
t = k*n - w
有t = k*n - w可以知道的,让一个指针在开始出,另外一个指针在w处,同时以相同的步幅移动,最后会在入口点相遇。
leetcode测试地址
/**
* 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 == NULL)
return false;
ListNode *slow_ptr = head;
ListNode *fast_ptr = head;
bool bool_loop = false;
while ( fast_ptr != NULL && fast_ptr->next != NULL && fast_ptr->next->next != NULL)
{
fast_ptr = fast_ptr->next->next;
slow_ptr = slow_ptr->next;
if ( fast_ptr == slow_ptr) //这里比较两个指针是否相等,应为val可能有相同的值
{
bool_loop = true;
break;
}
}
return bool_loop;
}
};
leetcode测试地址
/**
* 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) {
if (head == NULL)
return NULL;
ListNode *slow_ptr = head;
ListNode *fast_ptr = head;
bool bool_loop = false;
while ( fast_ptr != NULL && fast_ptr->next != NULL && fast_ptr->next->next != NULL)
{
fast_ptr = fast_ptr->next->next;
slow_ptr = slow_ptr->next;
if ( fast_ptr == slow_ptr )
{
bool_loop = true;
break;
}
}
if (!bool_loop)
return NULL;
ListNode *tmp_ptr = head;
while ( tmp_ptr != slow_ptr ) // //这里比较两个指针是否相等,应为val可能有相同的值
{
tmp_ptr = tmp_ptr->next;
slow_ptr = slow_ptr->next;
}
return tmp_ptr;
}
};
申请一个新的链表,第一个为哨兵节点,这样可以将边界的解法和正常情况统一起来。之后比较l1和l2,谁小谁放到新的里面。终止条件是有一个链表先为空了。
leetcode测试地址
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* guard = new ListNode(0);
ListNode* guard_new =guard;
while( l1!=NULL && l2!=NULL)
{
if( l1->val < l2->val )
{
guard->next = l1;
l1=l1->next;
guard = guard->next;
}else{
guard->next = l2;
l2 = l2->next;
guard = guard->next;
}
}
if( l1 != NULL )
{
guard->next = l1;
}else{
guard->next = l2;
}
return guard_new->next;
}
};
首先在头部增加一个哨兵节点,可以有效解决一个节点和两个节点的边界问题。申请了两个指针first和second,先让first和second相差n+1和位置(n+1位置是因为删除n时需要让second指向n-1的节点)。之后让first和second保持相同的幅度移动直到first==null。
leetcode代码测试地址
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* guard = new ListNode(0);
guard->next=head;
ListNode* first_ptr=guard;
ListNode* slow_ptr=guard;
int i=1;
for(i=1; i<=n+1; i++)
first_ptr=first_ptr->next;
while(first_ptr != NULL)
{
slow_ptr=slow_ptr->next;
first_ptr=first_ptr->next;
}
slow_ptr->next=slow_ptr->next->next;
return guard->next;
}
};
分成两种情况,一种是奇数的情况,退出的条件是f->next == NULL。
一种是偶数的情况,退出的条件是f == NULL。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* middleNode(ListNode* head) {
if(head==NULL || head->next == NULL)
return head;
ListNode* fast_ptr = head;
ListNode* slow_ptr = head;
while(fast_ptr != NULL && fast_ptr->next != NULL)
{
fast_ptr=fast_ptr->next->next;
slow_ptr=slow_ptr->next;
}
return slow_ptr;
}
};