第五天
链表的中间节点
876. 链表的中间结点 - 力扣(LeetCode)
使用快慢指针,fast指针一次走两个节点slow一次走一个节点.当fast或fast->next 走到NULL时我们的slow也就到了中间节点位置
struct ListNode* middleNode(struct ListNode* head)
{
if(head == NULL)
{
return NULL;
}
struct ListNode* fast = head;
struct ListNode* slow = head;
while(fast != NULL&&fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
删除链表的倒数第N个节点
19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
思路一(自己写法)
先遍历一遍数组得到数组长度然后通过数组长度和n(倒数第几的值)值相减的循环来得到使我们得到倒数第几的地址并我们先记录他上一个节点的地址最后处理特殊情况即可.
struct ListNode* removeNthFromEnd(struct ListNode* head, int n)
{
if(head == NULL)
return NULL;
struct ListNode* cur = head;
int len = 0;
while(cur != NULL)
{
cur = cur->next;
len++;
}
cur = head;
struct ListNode* prev = head;
for(int i = 0;i < len-n;i++)
{
prev = cur;
cur = cur->next;
}
if(len == n)
{
struct ListNode* tmp = head;
head = head->next;
free(tmp);
return head;
}
if(prev == cur)
{
free(cur);
return NULL;
}
prev->next = cur->next;
return head;
}
官方解法可以避免if语句去处理特殊情况不过有一点点难理解.但是整体思路相同.
思路二(双指针)
双指针的思路其实也很简单通过两个指针先让快指针先走n个节点再让慢节点和快捷点一起走最终当快指针走到空时结束(注:我写的是fast->next==NULL时退出是为了让慢指针指向要删除的前一个节点方便我们后面的删除).
struct ListNode* removeNthFromEnd(struct ListNode* head, int n)
{
struct ListNode* fast = head;
struct ListNode* slow = head;
if(head ==NULL)
{
return NULL;
}
if(head->next == NULL)
{
free(head);
return NULL;
}
for(int i =0;i<n;i++)
{
fast = fast->next;
}
while(fast != NULL&&fast->next != NULL)
{
slow = slow->next;
fast = fast->next;
}
if(fast == NULL)
{
struct ListNode* cur = head;
head = head->next;
free(cur);
return head;
}
struct ListNode* tmp = slow->next;
slow->next = tmp->next;
free(tmp);
return head;
}
|