day04-链表part02|24.两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题02.07.链表相交、142.环形链表Π

每日总结day04

写在前面:今天感冒还是依旧,我真的服了

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

题目

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

思路

  1. 使用一个虚拟头结点方便操作
  2. 用一个指针每次跳两个,并修改指针指向的下两个节点的位置
  3. 在修改时要使用一个temp指针,防止节点丢失

新思想

  1. 虚拟头结点统一操作

代码

class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head == null)
            return null;
        
        ListNode demmey = new ListNode(0);
        demmey.next = head;
        ListNode p = demmey;
        ListNode q = demmey;
        while(!(p.next == null || p.next.next == null)) {
            q = p.next.next;
            p.next.next = p.next.next.next;
            q.next = p.next;
            p.next = q;
            p = p.next.next;
        }
        return demmey.next;
    }
}

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

题目

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

思路

  1. 使用虚拟头结点
  2. 使用快慢指针,快指针比慢指针快N个节点
  3. 当快指针到达最后一个节点时,慢指针到达倒数第N+1个节点
  4. 删除倒数第N个节点即可

新思想

  1. 虚拟头结点
  2. 快慢指针的不同用法

代码

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode demmey = new ListNode(0);
        demmey.next = head;
        ListNode pre = demmey;
        ListNode cur = demmey;
        if(head == null || n <= 0)
            return null;
        while(pre != null && n != 0) {
            pre = pre.next;
            n--;
        }
        if(pre == null)
            return null;
        while(pre.next != null) {
            pre = pre.next;
            cur = cur.next;
        }
        cur.next = cur.next.next;
        return demmey.next;
    }
}

面试题02.07|链表相交

题目

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

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

思路

  1. 设置虚拟头结点
  2. 设置两个指针分别指向两个链表的起始位置
  3. 分别遍历两个链表得到二者的长度len_a、len_b
  4. 长的链表的指针向前移动|len_a-len_b|,因为链表是一直相交到末尾,所以一定是从剩余长度相等的地方开始相交的
  5. 然后两个指针同时移动,当指针指向同一个节点时结束

新思想

  1. 对链表特殊结构的特点进行分析

代码

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int len_a = 0;
        int len_b = 0;
        ListNode pa = headA;
        ListNode pb = headB;
        while(pa != null) {
            len_a++;
            pa = pa.next;
        }
        while(pb != null) {
            len_b++;
            pb = pb.next;
        }
        pa = headA;
        pb = headB;
        int diff = len_a - len_b;
        int i = 0;
        if(diff > 0) {
            while(--diff >= 0) {
                pa = pa.next;
            }
        } else {
            diff = -diff;
            while(--diff >= 0) {
                pb = pb.next;
            }
        }
        while(pa != pb && pa != null) {
            pa = pa.next;
            pb = pb.next;
        }
        if(pa != null)
            return pa;
        else
            return null;
    }
}

142|环形链表Π

题目

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

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

不允许修改 链表。

思路

  1. 设置快慢指针,快指针每次走两格,慢指针每次走一格
  2. 如果快指针或者快指针的下一个为null则没有环
  3. 如果快慢指针相遇了,说明有环
  4. 从头结点开始走一个指针,同时从快慢指针相遇的地方走一个指针,两个指针相遇的地方就是循环入口
  5. (这题新碰到对数学能力要求比较高)

新思想

  1. 对环形链表的特点进行分析
  2. 快慢指针的新用法
  3. (数学功底要好)

代码

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            while(fast == slow) {
                ListNode index1 = fast;
                ListNode index2 = head;
                while(index1 != index2) {
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值