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

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

  • 题解:
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    // 获取链表的结点个数
    public int size(ListNode head){
        // 如果传入空链表,直接返回链表大小为0
        if(head == null){
            return 0;
        }
        // 链表可以保证至少头结点不为空,长度至少为1
        ListNode cur = head;
        int size = 1;
        while(cur.next != null){
            cur = cur.next;
            size++;
        }
        return size;
    }
    public ListNode swapPairs(ListNode head) {
        ListNode dummyhead = new ListNode();
        dummyhead.next = head;

        ListNode current = dummyhead;

        if(size(head) % 2 == 0){
            // 如果链表长度为偶数
            while(current.next != null){
                ListNode temp = current.next;
                ListNode temp1 = current.next.next.next;
                current.next = current.next.next;
                current.next.next = temp;
                temp.next = temp1;
                current = current.next.next;
            }
        }else{
            // 如果链表长度为奇数
            while(current.next.next != null){
                ListNode temp = current.next;
                ListNode temp1 = current.next.next.next;
                current.next = current.next.next;
                current.next.next = temp;
                temp.next = temp1;
                current = current.next.next;
            }
        }

        return dummyhead.next;
    }
}

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

  • 题解(快慢指针解法):
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 快慢指针解法
        ListNode dummyhead = new ListNode();
        dummyhead.next = head;
        ListNode fast = dummyhead;
        ListNode low = dummyhead;
        // 为了保证low移动到待删除目标结点的前驱结点
        n++ ;
        // 将fast移动n+1步,(从fast往回数第n个,要把low停在倒数第n个结点的前驱结点)
        // 若n>链表长度,则fast停在尾结点后驱null
        while(n != 0 && fast != null){
            fast = fast.next;
            n--;
        }
        // fast和low同时后移,直到fast移到最后的null
        while(fast != null){
            fast = fast.next;
            low = low.next;
        }
        // 此时,low.next为倒数第n个结点
        low.next = low.next.next;
        return dummyhead.next;
    }
}

 面试题 02.07. 链表相交

  • 题解1(借鉴了大佬的题解,优雅,实在是优雅):
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    // 我走过你走的路 —— 我们终将彼此相遇
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        while(curA != curB){
            curA = curA==null ? headB : curA.next;
            curB = curB==null ? headA : curB.next;
        }
        return curA;
    }
}
  • 题解(自己写的,但是系统显示超时,Emm感觉思路没问题但是就是超时,望大佬指正) :
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    // 得到传入链表的长度
    public int size(ListNode head){
        // 如果传入链表为空,直接返回0
        if(head == null){
            return 0;
        }
        // 此时至少链表不为空
        int size = 1;
        ListNode cur = head;
        while(cur.next != null){
            cur = cur.next;
            size++;
        }
        return size;
    }
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        int result = size(headA) - size(headB);
        // 当链表A长度>=链表B长度时
        if(result >= 0){
            // 将两个链表末端对齐
            while(result != 0 && curA.next != null){
                curA = curA.next;
                result--;
            }
            while(curA != null || curB != null){
                // 当A、B指针均未走到末尾向后搜索时
                // 遇到两个指针相等(即两个结点相同)
                if(curA == curB){
                    return curA;
                }
            }
            // 若无交点,返回null
            return null;
        }else{
            // 当B链表长度>A链表长度时
            // 将两个链表末端对齐
            while(result != 0 && curB.next != null){
                curB = curB.next;
                result++;
            }
            while(curA != null || curB != null){
                // 当A、B指针均未走到末尾向后搜索时
                // 遇到两个指针相等(即两个结点相同)
                if(curA == curB){
                    return curB;
                }
            }
            // 若无交点,返回null
            return null;
        }
    }
}

 142.环形链表II

        tips:需要注意的点是:经过推导,将环拉直,不难得出low在进入环之后,走完一圈之前必然被fast追上过,所以设low为x+y。

  • 题解(数学推导是重点):
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    // 快慢指针解法
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode low = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            low = low.next;
            // 遇到环,快慢指针相遇
            if(fast == low){
                ListNode cur1 = fast;
                ListNode cur2 = head;
                while(cur1 != cur2){
                    cur1 = cur1.next;
                    cur2 = cur2.next;
                }
                // cur1/cur2相遇点即为环入口
                return cur1;
            }
        }
        // fast走完未遇到环,说明链表无环,返回null
        return null;
    }
}

  • 29
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值