代码随想录算法训练营第四天 |24. 两两交换链表中的节点 19.删除链表的倒数第N个节点 面试题 02.07. 链表相交 142.环形链表II

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

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

示例 1:

输入:head = [1,2,3,4]
输出:[2,1,4,3]

示例 2:

输入:head = []
输出:[]

示例 3:

输入:head = [1]
输出:[1]

和之前逆置链表的思路比较类似,设置虚拟头结点,然后设置temp,之后交换位置即可

错误代码:
 

class Solution 
{
public:
    ListNode* swapPairs(ListNode* head)
    {
        ListNode* VirtualHead = new ListNode(0);
        VirtualHead->next = head;
        ListNode* left,right,temp;
        left = VirtualHead->next;
        while(left->next != NULL)
        {
            
            right = left->next;
            VirtualHead->next = right;
            left->next =right->next;
            right->next = left;
            VirtualHead = left;
        }//错误代码,不应该在while中修改virtualhead,这样会导致头结点丢失
    }
};

正确代码,注意事项在注释里

class Solution 
{
public:
    ListNode* swapPairs(ListNode* head)
    {
        if(head == NULL || head->next == NULL) return head;//先提前判断是否非空
        ListNode* VirtualHead = new ListNode(0);
        VirtualHead->next = head;
        ListNode* left,*right,*temphead;//注意*号两个都要打上
        left = VirtualHead->next;
        right = left->next;
        temphead = VirtualHead;        
        while(temphead->next != NULL && temphead->next->next != NULL)
        {
            left = temphead->next;
            right = left->next;//注意这个放前面,防止出现错误,具体原因不清楚,可能是防止指向位置空间            

            temphead->next = right;
            left->next =right->next;
            right->next = left;

            temphead = left;

        }
        ListNode* result = VirtualHead->next;
        return result;
    }
};

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

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例 1:

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]

示例 2:

输入:head = [1], n = 1
输出:[]

示例 3:

输入:head = [1,2], n = 1
输出:[1]

主要思路,人为制造长度为n的尺子

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(head == NULL || head->next == NULL) return NULL;

        ListNode* virtualhead =new ListNode(0);
        virtualhead->next = head;//注意使用虚拟头节点来确定真正的头节点,因为删除的可能就是头节点
        ListNode *fast,*slow;
        fast = head;

        while(n--)
        {
            fast = fast->next;
        }
        slow = virtualhead;
        while(fast != NULL)//看不清可以画图理解
        {
            fast = fast->next;
            slow = slow->next;
        }//此时slow指向目标的前一个结点
        slow->next = slow->next->next;
        return virtualhead->next;
    }
};

面试题 02.07. 链表相交

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

示例 1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

这不考研原题吗,某一年的数据结构代码大题

思路就是先统计两个链表的长度,得到差值,然后调整起始位置,一起向后,直到遇到相同的结点为止。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int lengthA = 0 ,lengthB = 0;
        ListNode *nodeA = headA,*nodeB = headB;
        while(nodeA != NULL)
        {
            nodeA = nodeA->next;
            lengthA++;
        }
        while(nodeB != NULL)
        {
            nodeB = nodeB->next;
            lengthB++;
        }       
        //注意这里我们让最长的那个是A,短的是B,方便后面处理

        if(lengthB > lengthA)
        {
            swap(lengthA,lengthB);
            swap(headA,headB);
        }
        nodeA = headA;
        nodeB = headB;
        int cha = lengthA - lengthB;

        while(cha--)
        {
            nodeA = nodeA->next;
        }
        while(nodeA != NULL)
        {

            if(nodeA == nodeB)
            {
                return nodeA;
            }//注意先判断再提交
            nodeA = nodeA->next;         
            nodeB = nodeB->next;              
        }
        return NULL; 
    }
};

142. 环形链表 II

 

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

这题很复杂,需要从数学上进行理解,看随想录的PPT代码随想录

不看解析我很难想出来

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值