代码随想录算法04 | LC24、19、面试题 02.07、142

Leetcode24. 两两交换链表中的节点

题目链接:

[24. 两两交换链表中的节点 - 力扣(Leetcode)]

思路:

  • 题意为两两交换即两两为一组进行指针操作后循环
  • 采用头结点

24.两两交换链表中的节点1

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode *headNode = new ListNode(0);
        headNode->next=head;
        ListNode *cur =headNode;
        while(cur->next!=nullptr&&cur->next->next!=nullptr)
        {
            ListNode *node1=cur->next;
            ListNode *node3=cur->next->next->next;
            cur->next=node1->next;
            cur->next->next=node1;
            node1->next=node3;
            cur=node1;
        }  
        return headNode->next;  
        }
};

注意的问题:

  • 注意每次循环后cur的位置,理清中间需要存储的变量即可

Leetcode19. 删除链表的倒数第 N 个结点

题目链接:

[19. 删除链表的倒数第 N 个结点 - 力扣(Leetcode)]

思路:

  • 快慢指针
    • 快指针先走n步
    • 慢指针再与其一同出发直至快指针走至尽头
    • ==注意:==删除结点需找到前一个结点,因此设一个虚拟头结点作为起始快慢指针位置
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *headNode = new ListNode(0);
        ListNode *fast =headNode;
        ListNode *slow =headNode;
        headNode->next=head;
        while(n--)
        {
            fast=fast->next;
        }
        while(fast->next!=nullptr)
        {
            fast=fast->next;
            slow=slow->next;
        }
        slow->next=slow->next->next;
        return headNode->next;
    }
};

Leetcode面试题 02.07. 链表相交

题目链接:

[面试题 02.07. 链表相交 - 力扣(Leetcode)]

思路:

  • 与上一题类似使用快慢指针
  • 区别在于不知道快指针先走几步以及不知道哪个链表快
    • 首先遍历一遍记录两个链表长度
    • 快指针即链表长的,慢指针即链表短的
    • 同理快指针先走链表长度差,直至快慢指针相遇
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *cur1=headA;
        ListNode *cur2=headB;
        int a=1,b=1;
        while(cur1!=NULL)
        {
            cur1=cur1->next;
            a++;
        }
        while(cur2!=NULL)
        {
            cur2=cur2->next;
            b++;
        }
        int sub=0;
        cur1=headA;
        cur2=headB;
        if(a>b)
        {
            sub=a-b;
            while(sub--)
            {
                cur1=cur1->next;
            }
        }
        else{
            sub=b-a;
            while(sub--)
            {
                cur2=cur2->next;
            }
        }
        while(cur1!=NULL&&cur2!=NULL)
        {
            if(cur1==cur2)
            {
                return cur1;
            }
            cur1=cur1->next;
            cur2=cur2->next;
        }
        return NULL;

    }
};

Leetcode142. 环形链表 II

题目链接:

[142. 环形链表 II - 力扣(Leetcode)]

思路及遇到的问题:

  • 只能想到快慢指针,快指针一次走两步,慢指针一次走一步,若有环,快慢指针则必然相遇。

  • 确定带环结点

    • 一开始误以为相遇结点即为带环开始结点

    • 推导过程

      [数学公式推导]

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *headNode =new ListNode(0);
        headNode->next=head;
        ListNode *fast=headNode;
        ListNode *slow=headNode;
        ListNode *tmp;
        while(fast->next!=NULL&&fast->next->next!=NULL&&fast->next->next!=slow->next)
        {
            fast=fast->next->next;
            slow=slow->next;
        }
        tmp=slow->next;
        slow=headNode;
        while(tmp!=NULL)
        {
            slow=slow->next;
            tmp=tmp->next;
            if(slow==tmp)
                return slow;
        }
        return NULL;
    }
};

遇到的问题:第一个while循环可能出现空指针->于是改成:fast->next->next!=slow->next&&fast->next!=NULL&&fast->next->next!=NULL这样会先判断fast->next->next!=slow->next导致加上的空指针判断毫无意义

代码优化:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast) {
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2;
            }
        }
        return NULL;
    }
};

总结

熟悉快慢指针的灵活运用

对于Leetcode142带环结点的推导须反复揣摩

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值