首页 > 其他分享 >day04 打卡24. 两两交换链表中的节点 19.删除链表的倒数第N个节点 142.环形链表II

day04 打卡24. 两两交换链表中的节点 19.删除链表的倒数第N个节点 142.环形链表II

时间:2023-03-04 19:35:15浏览次数:59  
标签:dummy head ListNode cur next 链表 打卡 节点

day04 打卡24. 两两交换链表中的节点 19.删除链表的倒数第N个节点 142.环形链表II

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

24题目链接

1.第一次想的思路:使用count记录当前是第几个节点,每当count为偶数时,进行交换两个相邻的节点。while中代码可以实现,但是当返回头节点的时候不知道怎么放回。因为虚拟节点后的头节点换了。以下是我的思路伪代码:

ListNode dummy = new ListNode(-1, head);
ListNode pre = dummy;
ListNode cur = head;
ListNode temp = null;
int count = 1;
while (cur != null && cur.next != null) {
        if (count%2 == 0) {
          temp = cur.next;
          cur.next = pre;
          
          pre.next = temp;
        } else {
          pre = cur;
          cur = cur.next;
        }
        count++;
}
// 交换完成,但是找不到头节点
return ?

2.去看了代码随想录。发现了(我思考的)参与交换的节点是2个(即需要交换的两个节点),这就有了上面的短路。而代码随想录的动态图是3个节点的交换,而且不需要count计数,直接把cur变成下一个需要交换的第一个节点即可。如果不满足两个节点,也不需要进入while循环了,无需交换。我写下了以下的代码:

以dummy->1->2->3->4->null为例:

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(-1, head);
        ListNode pre = dummy; // dummy, next:1
        ListNode cur = head; // 1, next: 2
        ListNode temp = null;
        while (cur != null && cur.next != null) {
            pre.next = cur.next; // 这句话让dummy.next = 2
            temp = cur.next.next; // 记住 不需要进行交换的后面的节点即3->4->null
            cur.next = temp; // 这句话让1.next = 3
            // 此时的排序 dummy->2  ; 1->3->4->null
            pre.next.next = cur; // 这句话让2.next = 1
            // 此时的排序 dummy->2->1->3->4->null
            // 下一个进行交换的节点cur是3,pre要是1
            pre = cur;
            cur = temp;
        }
        return dummy.next;
    }
}

3.递归法。根据03.03的206题目递归法的推出,我写出了对应版本的递归法。递归结束条件==循环结束条件,主体交换操作代码一致。本来我写了return pre.next,但是这样返回的是null,虽然节点排序完成。不需要return数值,这就涉及到了java方法传参数。基本类型总是按值传递。对于对象来说,是将对象的引用也就是副本传递给了方法,在方法中只有对对象进行修改才能影响该对象的值,操作对象的引用时是无法影响对象。

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(-1, head);
        swapPairs(dummy, head);
        return dummy.next;
    }

    public void swapPairs(ListNode pre, ListNode cur) {
        if (cur == null || cur.next == null) {
            return;
        }
        pre.next = cur.next;
        ListNode temp = cur.next.next;
        cur.next = temp;
        pre.next.next = cur;
        swapPairs(cur, temp);
    }
}

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

19题目链接

1.想不出来比较简单的方式。决定先把整个翻转,在去删除,再去翻转。

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        head = reserve(head);
        head = del(head, n);
        return reserve(head);
    }

    public ListNode del(ListNode head, int n) {
        ListNode dummy = new ListNode(-1, head);
        ListNode pre = dummy;
        for(int i = 1; i<n ; i++) {
            pre = pre.next;
        }
        pre.next = pre.next.next;
        return dummy.next;
    }

    public ListNode reserve(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        ListNode temp = null;
        while (cur != null) {
            temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
}

2.看来视频讲解在写的代码。主要的思想就是使用快慢指针。首先要删除一个节点需要得到这个节点的前驱节点。

因为链表长度是不变的,我们称呼为size。快指针先走n步,剩下的步数就是size-n。而size-n就是我们正常从链头开始走到需要被删除节点的距离。这时的慢指针还在原点,慢指针和快指针同时开始走路,当快指针到达null(链尾)的时候,慢指针就走到了要删除的节点。

因为我们真的需要操作的是要删除的节点的前一个,所以快指针先走n+1步,慢指针就走size-n-1步,正好到达前驱节点。

视频链接

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(-1, head);
        ListNode fast = dummy;
        ListNode slow = dummy;
        for (int i = 0; i<n+1 ; i++) {
            fast = fast.next;
        }
        while (fast != null) {
            fast = fast.next;
            slow = slow.next;
        }
        // slow现在的位置就是要删除的节点的前驱节点
        slow.next = slow.next.next;
        return dummy.next;
    }
}

面试题 02.07. 链表相交

面试题 02.07. 链表相交链接

1.没有思路,直接看代码随想录的.

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode aCur = headA;
        ListNode bCur = headB;
        int aSize = getSize(headA);
        int bSize = getSize(headB);
        // 长度查
        int gap = Math.abs(aSize - bSize);
        if (aSize > bSize) {
            // b对齐a的尾巴,操作a指针
            for (int i = 0 ; i<gap ; i++) {
                aCur = aCur.next;
            }
        } else {
            // a对齐b的尾巴,操作b指针
            for (int i = 0 ; i<gap ; i++) {
                bCur = bCur.next;
            }
        }
        while (aCur != null && bCur != null) {
            if (aCur == bCur) {
                return aCur;
            }
            aCur = aCur.next;
            bCur = bCur.next;
        }
        return null;
    }

    public int getSize(ListNode head) {
        int size = 0;
        while (head != null) {
            head = head.next;
            size++;
        }
        return size;
    }
}

142. 环形链表 II

142题目链接

1.直接看视频,比较清楚 视频链接

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;
            if (fast == slow) {
                // 说明快慢指针相遇,则一定有环
                ListNode index1 = fast; // 相遇的位置
                ListNode index2 = head;
                while (index1 != index2) {
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}

参考资料

java 值传递 数组传递

代码随想录

标签:dummy,head,ListNode,cur,next,链表,打卡,节点
From: https://www.cnblogs.com/zzzsl/p/17178898.html

相关文章

  • Android学习-每日打卡APP-实现每日打卡
    继续写我的打卡APP-完成了每日打卡的功能,其实还是比较简单,因为和注册一样都是插入的过程同时还能实现自动计数的功能,把坚持天数自动计算出来,打卡后插入数据库效果,可以看......
  • Android-每日打卡APP-实现登录功能
    每日打卡APP新的进展-实现登录功能-昨天已经把注册功能实现了,今天也很快把登录功能做了出来,然后接着着手做其他功能,打卡功能写在下一篇博客能够实现登录和注册,注册相关的......
  • 求二叉树节点的最大距离
    距离即为节点间的边数。code:structNode{Node*left;Node*right;intnmaxleft;intnmaxright;intvhvalue;};intans;//答案intfindmaxval(Node*ro......
  • 填充每个节点的下一个右侧节点的指针
    填充每个节点的下一个右侧节点的指针给定一个二叉树:structNode{intval;Node*left;Node*right;Node*next;}填充它的每个next指针,让这个指针指向其下一个右......
  • 每日打卡
    MySQL表的增删改查(基础)1.新增(Create)1.1单行数据+全列插入1.2多行数据+指定列2.查询(Retrieve)2.1全列查询2.2指定列查询2.3查询字段为表达式2.4别名2.5去重......
  • Android学习-每日打卡APP-进展
    今天课比较多,但是还是要抽出时间写安卓,又有了一些小进展,将数据库的部分代码写了出来可以参考一下packagecom.example.clockappliction;importandroid.content.Conte......
  • 解决空白幽灵节点
    空白幽灵节点是什么?这个“空白节点”永远透明,不占据任何宽度,看不见也无法通过脚本获取,就好像幽灵一样,但又确确实实地存在,表现如同文本节点一样,因此,我称之为“幽灵空白节点......
  • vm-集群初始化3节点搭建(node01、node02、node03)
    首先确保windows系统,对应的vmware 服务都是正常运行修改虚拟机对应的主机名字设置虚拟机的主机名,重启生效 reboot修改对应的配置hosts 配置文件,vim/etc/hosts关......
  • 代码随想录算法训练营第四天 | 24. 两两交换链表中的节点、19.删除链表的倒数第N个节
    24.两两交换链表中的节点-力扣(LeetCode)给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交......
  • deploy资源-配置节点亲和性以及污点容忍
    apiVersion:apps/v1kind:Deploymentmetadata:name:health-check-deploymentlabels:app:health-checkspec:replicas:1selector:matchLabels......