代码随想录Day4:链表

24. 两两交换链表中的节点leetcode地址

自己写的0指2,1指3,然后2再指1,这样可以少一个中间量

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode cur = dummy;
        while(cur.next != null && cur.next.next != null){
            ListNode node = cur.next;
            cur.next = cur.next.next;
            node.next = cur.next.next;
            cur.next.next = node;
            cur = cur.next.next;
            
        }
        return dummy.next;
    }
}
class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(0, head); // 用哨兵节点简化代码逻辑
        ListNode node0 = dummy;
        ListNode node1 = head;
        while (node1 != null && node1.next != null) { // 至少有两个节点
            ListNode node2 = node1.next;
            ListNode node3 = node2.next;

            node0.next = node2; // 0 -> 2
            node2.next = node1; // 2 -> 1
            node1.next = node3; // 1 -> 3

            node0 = node1; // 下一轮交换,0 是 1
            node1 = node3; // 下一轮交换,1 是 3
        }
        return dummy.next; // 返回新链表的头节点
    }
}

差灵山爱抚的题解这样写,这样所有节点都变变量表示更加清晰,值得学习

感谢爱抚,欢迎关注 B站@灵茶山艾府

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

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0);
        ListNode right = dummy;
        ListNode left = dummy;
        dummy.next = head;
        while(n-- > 0){
            right = right.next;
        }
        while(right.next != null){
            left = left.next;
            right = right.next;
        }
        left.next = left.next.next;
        return dummy.next;
    }
}

快慢指针,如果先遍历算长度size,在遍历size-n,是两层
如果用快慢指针,让右指针先动n,再左右一起动,把后n转换成前n

代码参考了爱抚大人,爱抚大人的编码风格真的爱了,写的简直太漂亮了,想谈

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 由于可能会删除链表头部,用哨兵节点简化代码
        ListNode dummy = new ListNode(0, head);
        ListNode left = dummy, right = dummy;
        while (n-- > 0) {
            right = right.next; // 右指针先向右走 n 步
        }
        while (right.next != null) {
            left = left.next;
            right = right.next; // 左右指针一起走
        }
        left.next = left.next.next; // 左指针的下一个节点就是倒数第 n 个节点
        return dummy.next;
    }
}

作者:灵茶山艾府
链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/solutions/2004057/ru-he-shan-chu-jie-dian-liu-fen-zhong-ga-xpfs/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

160.链表相交leetcode地址

(版本一)先行移动长链表实现同步移动
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        int lenA = 0, lenB = 0;
        while (curA != null) { // 求链表A的长度
            lenA++;
            curA = curA.next;
        }
        while (curB != null) { // 求链表B的长度
            lenB++;
            curB = curB.next;
        }
        curA = headA;
        curB = headB;
        // 让curA为最长链表的头,lenA为其长度
        if (lenB > lenA) {
            //1. swap (lenA, lenB);
            int tmpLen = lenA;
            lenA = lenB;
            lenB = tmpLen;
            //2. swap (curA, curB);
            ListNode tmpNode = curA;
            curA = curB;
            curB = tmpNode;
        }
        // 求长度差
        int gap = lenA - lenB;
        // 让curA和curB在同一起点上(末尾位置对齐)
        while (gap-- > 0) {
            curA = curA.next;
        }
        // 遍历curA 和 curB,遇到相同则直接返回
        while (curA != null) {
            if (curA == curB) {
                return curA;
            }
            curA = curA.next;
            curB = curB.next;
        }
        return null;
    }

}

(版本二) 合并链表实现同步移动
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
		// p1 指向 A 链表头结点,p2 指向 B 链表头结点
		ListNode p1 = headA, p2 = headB;
		while (p1 != p2) {
			// p1 走一步,如果走到 A 链表末尾,转到 B 链表
			if (p1 == null) p1 = headB;
			else            p1 = p1.next;
			// p2 走一步,如果走到 B 链表末尾,转到 A 链表
			if (p2 == null) p2 = headA;
			else            p2 = p2.next;
		}
		return p1;
    }
}

方法一先把B移动到跟A末尾对齐,再找相同的,

方法二很巧妙,如果有相同的,那走都过两边A+B的路程是一样的

142.环形链表II leetcode地址

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode first = head;
        ListNode slow = head;
        while(first != null && first.next != null){
            first = first.next.next;
            slow = slow.next;
            if(first == slow){
                while(first != head){
                first = first.next;
                head = head.next; 
                }
                return first;
            }
        }
        return null;
    }
}

快指针两步两步的跳,所以进入循环的条件是,快指针和快指针的下个不为空。

链表总结

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值