代码随想录day04

代码随想录day04

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

先引入一个虚拟头结点,排除一些特殊情况
在这里插入图片描述

class Solution {
    public ListNode swapPairs(ListNode head) {
        //虚拟头结点
        ListNode newHead = new ListNode(-1);
        newHead.next=head;

        ListNode curNode=newHead;
        ListNode tempNode;
        ListNode firtNode;
        ListNode secondNode;
        while(curNode.next != null && curNode.next.next != null){
            firtNode = curNode.next;
            secondNode = curNode.next.next;
            tempNode = curNode.next.next.next;
			
			//交换的三个步骤
            curNode.next = secondNode;
            secondNode.next = firtNode;
            firtNode.next =tempNode;
            //移动虚拟头结点的三个位置以实现下一组交换
            curNode=firtNode;
        }

        return newHead.next;

    }
}

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

class Solution {

    public ListNode removeNthFromEnd(ListNode head, int n) {
        //虚拟头结点
        ListNode newHead=new ListNode(-1);
        newHead.next=head;
        //快慢指针
        ListNode fast=newHead;
        ListNode slow=newHead;
        //将快指针先移动n个位置
        while(n != 0){
            fast = fast.next;
            n--;
        }
        //快慢指针同时移动,当快指针移动至链表末尾时,慢指针刚好是我们要删除节点的前一个节点
        while(fast.next != null){
            fast = fast.next;
            slow = slow.next;
        }
        //删除目标节点
        slow.next = slow.next.next;
        //防止头结点被删除,故返回cur.next而不是head
        return cur.next;
    }
}

面试题02.07.链表相交

辅助栈

将两个链表压入栈中,自栈顶逐渐向栈尾比较,找出交叉的子链表
public class Solution {  
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {  
        if (headA == null || headB == null) {  
            return null;  
        }  
        Stack<ListNode> stackA = new Stack<>();  
        Stack<ListNode> stackB = new Stack<>();  
          
        ListNode dummyA = new ListNode(0, headA);  
        ListNode dummyB = new ListNode(0, headB);  
          
        ListNode curA = dummyA;  
        ListNode curB = dummyB;  
        
        //将链表中内容压入栈中
        while (curA != null) {  
            stackA.push(curA);  
            curA = curA.next;  
        }  

        while (curB != null) {  
            stackB.push(curB);  
            curB = curB.next;  
        }  
        
        //将栈顶进行比较
        while (!stackA.isEmpty() && !stackB.isEmpty() && stackA.peek() == stackB.peek()) {  
            stackA.pop();  
            stackB.pop();  
        }  
          
        if (stackA.isEmpty() && stackB.isEmpty()) {  
            return null;  
        }  
           
        return stackA.isEmpty() ? stackB.peek().next : stackA.peek().next;  
    }  
}

双指针

A链表遍历完之后遍历B链表至交叉结点所经过的路程为a +(b-c)
B链表遍历完之后遍历B链表至交叉结点所经过的路程为b +(a-c)
二者相等

大佬解释

public class Solution {  
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {  
        if (headA == null || headB == null) {  
            return null;  
        }  
      
        ListNode a = headA;  
        ListNode b = headB;  
      
        // 先让a和b遍历各自的链表,当a到达尾部时指向headB的头节点,当b到达尾部时指向headA的头节点  
        while (a != b) {  
            a = (a == null) ? headB : a.next;  
            b = (b == null) ? headA : b.next;  
        }  
      
        // 如果链表相交,a和b会在交点相遇;如果不相交,它们会同时指向null  
        return a;  
    }
}

142.环形链表II

图中直线段代表非环部分,圈代表环形部分
fast和slow两个指针都从head出发fast每次移动两个节点,slow每次移动一个节点,当二者相遇时
fast走了2k,slow走了k,fast比slow多走的部分是在绕环走,故k就是环的长度
在这里插入图片描述
我们假设相遇点距环起点的距离为m
故:
由head距离环起点的距离为k-m
相遇点绕环走至环起点的距离为k-m
此时两个指针都在相遇点,我们将slow指针移动至head位置,让二者以一个节点的速度出发,则刚好在环起点位置相遇,返回环起点
在这里插入图片描述

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast,slow;
        fast = 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;
        }
        
        slow=head;
        while(slow != fast){
            fast = fast.next;
            slow = slow.next;
        }

        return slow;    
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值