代码随想录-4day:24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点 、链表相交 、142.环形链表II

一、两两交换链表中的节点

本题主要理解递归和创建虚拟头结点两个方法,主要是理清楚指针指向,这个是最重要的一步:

新链表展开后就是cur->2->1->3->4->5->NULL  ,下一次需要跳到“1”位置继续遍历。

struct ListNode* swapPairs(struct ListNode* head) {
    struct ListNode* newhead  = (struct ListNode*)malloc(sizeof(struct ListNode));
    newhead->next = head;

    //终止条件:1 如果是空链表; 2 偶数个链表 3 奇数个链表
    struct ListNode* cur = newhead;
    while(cur->next !=NULL && cur->next->next != NULL)
    {
        struct ListNode* tmp = cur->next;//第一个节点
        struct ListNode* tmp_1 = cur->next->next->next;//记录下第三个节点
        /**画图比较清晰**/
        cur->next = cur->next->next;
        cur->next->next = tmp;
        cur->next->next->next = tmp_1;
        cur = cur->next->next;
    }
    return newhead->next;//一开始head 已经交换,注意头结点位置
}

另外一个方法是递归,递归思路可以这样理解,找到最后一次迭代,往前推:

struct ListNode* swapPairs(struct ListNode* head){
    //递归结束条件:头节点不存在或头节点的下一个节点不存在。此时不需要交换,直接返回head
    if(!head || !head->next)
        return head;
    //创建一个节点指针类型保存头结点下一个节点
    struct ListNode *newHead = head->next;
    //更改头结点+2位节点后的值,并将头结点的next指针指向这个更改过的list
    head->next = swapPairs(newHead->next);
    //将新的头结点的next指针指向老的头节点
    newHead->next = head;
    return newHead;
}
/**上面是代码随想录的写法**/

二、.删除链表的倒数第N个节点 

删除倒数第N个节点,用双指针的办法,首先fast向前进N+1个节点,slow=0位置处,当fast==NULL时候,fast移动了LEN-N个,slow同步移动了LEN-N个,位置来到了倒数N位置的前一个,这样就能释放掉N个节点。

 /**删除链表倒数第N个,用快慢指针**/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    //创建新节点,用来处理头结点,方便统一处理头结点。
    struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummyHead->next = head;
    struct ListNode* slow = dummyHead;
    struct ListNode* fast = dummyHead;

    int setp = 0;
    while(fast)
    {
        fast = fast->next;
        if(n== setp)
        {
            break;
        }
        setp++;
    }

    while(fast)
    {
        slow = slow->next;
        fast = fast->next;
    }
    /**删除节点**/
    struct ListNode* tmp = slow->next;
    slow->next = tmp->next;
    return dummyHead->next;
}

注意点: 1 fast应该移动N+1;2 最后应该dummy->head(这个节点一定存在),原head可能是NULL。

三、链表相交

链表相交的题目,一开始并没有理解到相交是什么意思,后面看了代码随想录和code,明白是指针相等,一旦存储节点的地址相等,说明相交,记住这一点,这个题目就清晰了。

首先对齐两个链表,从右往左对齐。然后依次遍历,当listNode A = B,返回该节点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
int lenA = 0;
int lenB = 0;
struct ListNode* curA = headA;
struct ListNode* curB = headB;

while(curA)
{
    lenA++;
    curA = curA->next;
}
while(curB)
{
    lenB++;
    curB = curB->next;
}
int step = lenA > lenB ? lenA - lenB: lenB - lenA;

int flg = 0;
flg = lenA > lenB? 0 : 1;//A>B 0   A<=B 1
curA = headA;
curB = headB;
while(step--)
{
  if(flg == 0)
  {
    curA = curA->next;
  }
  else
  {
    curB = curB->next;
  }
}

while(curA || curB)
{
    if(curA == curB)
    {
    return curA ;
    }
    curA = curA->next;
    curB = curB->next;
}
return NULL;
}

四、环形链表II 

根据代码随想录的讲解(链接:代码随想录),主要是需要理解到环形链表相遇时候的公式推导,分为两个部分:1 两个节点相遇时候的节点位置;2 推导环形入口点的公式;

struct ListNode *detectCycle(struct ListNode *head) {
    //slow走一步 fast走2步,直到fast结束
    struct ListNode * slow = head;
    struct ListNode * fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
        {
            /**第一次两个节点相遇,从该点开始,一直遍历,直到两点相等就是入口**/
            struct ListNode* indx1 = slow;
            struct ListNode* indx2 = head;
            while(indx1 != indx2)
            {
                indx1 = indx1->next;
                indx2 = indx2->next;
            }
            return indx2;
        }
    }

    return NULL;
}

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值