• LeetCode 链表题 ( Java )


    leetcode 237. 删除链表中的节点

    链接:https://leetcode-cn.com/problems/delete-node-in-a-linked-list/

    示例 :

    输入: head = [4,5,1,9], node = 5
    输出: [4,1,9]
    解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

     这道题比较简单,修改之前节点的 next 指针,使其指向之后的节点

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public void deleteNode(ListNode node) {
            node.val = node.next.val;
            node.next = node.next.next;
        }
    }

    leetcode 160. 相交链表

    链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/

    编写一个程序,找到两个单链表相交的起始节点。

    如下面的两个链表:

    在节点 c1 开始相交。要求返回 c1 这个节点。

    先得到两条链表的长度差 offset,再将长链表跳过 offset 个节点,然后再让这两个链表轮流逐个遍历节点,直到相遇。

    比如上图 A 和 B 差一个长度差为 1,先跳过 b1 这个结点到达 b2,然后 A 开始从 a1 遍历,到达 a2, B 到达 b3; 随后 A 到达 c1,B 到达 c1,两点相遇,返回 c1. 

    public class Solution {
        public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
            if(headA == null || headB == null)
                return null;
    
            int lengthA = getListLength(headA);
            int lengthB = getListLength(headB);
            ListNode longList = headA;
            ListNode shortList = headB;
            int offset = Math.abs(lengthA - lengthB);
            if(lengthA < lengthB){
                longList = headB;
                shortList = headA;
            }
            for(int i=0; i < offset; i++){
                longList = longList.next;
            }
            while(shortList != longList){
                shortList = shortList.next;
                longList = longList.next;
            }
            return shortList;
        }
        public int getListLength(ListNode p){
            int length = 0;
            while(p != null){
                length++;
                p = p.next;
            }
            return length;
        }
    }

    我又看了这道题的题解,看到有其他解法:两条链表先遍历一轮(消除长度差),当链表到达结尾的时候,反而让到达链表末尾的节点指向另一个链表的头部,然后再接着遍历,这样就消除了两条链表的长度差,可以大致理解为:两个人以同样的速度跑步,跑的路程也一致,那么肯定会同一个时间点到达终点。

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) return null;
        ListNode pA = headA, pB = headB;
        while (pA != pB) {
            pA = pA == null ? headB : pA.next;
            pB = pB == null ? headA : pB.next;
        }
        return pA;
    }

    leetcode 206. 反转链表

    示例:

    输入: 1->2->3->4->5->NULL
    输出: 5->4->3->2->1->NULL

     此题的思路是逐个反转,先变成 NULL<-1  2->3->4->5->NULL; 然后是 1<-2  3->4->5->NULL; 接着是 1<-2<-3  4->5->NULL,以此类推。那么我们首先就要先创建一个空节点为 prev,使得 1 指向它,但是,需要先把 2 这个节点保存起来,不然当 1 指向 NULL 后就失去了 2 以后的数据。完成第一次反转后就一直迭代下去。可能表达得不太行,看代码吧:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode reverseList(ListNode head) {
            ListNode prev = null;
            while(head != null) {
                ListNode next = head.next;
                head.next = prev;           // 翻转
                
                prev = head;
                head = next;
            }
            return prev;
        }
    }

    如果文字解释看不懂,代码也看不懂,那就视频吧,推荐这个小姐姐讲的   用Java解决翻转链表 Leetcode206 Reverse Linked List 

    leetcode 141. 环形链表

    给定一个链表,判断链表中是否有环。

    为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

    示例 1:

    输入:head = [3,2,0,-4], pos = 1
    输出:true
    解释:链表中有一个环,其尾部连接到第二个节点。

             

    示例 3:

    输入:head = [1], pos = -1
    输出:false
    解释:链表中没有环。
    

             

    (1) 哈希

      遇到这种类型得题目一般大部分都是用 hash ,通过遍历把每个节点存起来,如果该节点后续还被访问到,则表示该链表为环形链表。

    public boolean hasCycle(ListNode head) {
        Set<ListNode> nodes = new HashSet<>();
        while (head != null) {
            if (nodes.contains(head)) {
                return true;
            } else {
                nodes.add(head);
            }
            head = head.next;
        }
        return false;
    }

    (2)双指针

     定义两个指针,从 head 开始,慢指针移动一步,快指针移动两步,如果两个指针相遇则为环形链表,否则不是。这个道理就跟两个不同速度的人在同一条跑道上跑步一样,如果是环形的总会相遇。

    public boolean hasCycle(ListNode head) {
            if (head == null || head.next == null)
                return false;
            ListNode slow = head;
            ListNode fast = head.next;
            while(fast != null && fast.next != null) {
                if (slow == fast){
                    return true;
                }
                slow = slow.next;
                fast = fast.next.next;
            }
            return false;
        }

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

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

    示例:

    给定一个链表: 1->2->3->4->5, 和 n = 2.
    当删除了倒数第二个节点后,链表变为 1->2->3->5.

    (1)第一种方法:由于不清楚链表的长度,因此可以先遍历链表得到其长度,然后第二次遍历将倒数第N个节点删除,即被删除节点的前一个节点指向删除节点的后一个节点:

    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        int length  = 0;
        ListNode list = head;
        while (list != null) {
            length++;
            list = list.next;
        }
        length -= n;
        list = dummy;
        while (length > 0) {
            length--;
            list = list.next;
        }
        list.next = list.next.next;
        return dummy.next;
    }

    (2)第二种方法:使用双指针,先让其中一个指针走 N+1 步,然后两个指针同时移动,到达被删除节点的前一个节点时把它删除:

        

         

        

         

    public ListNode removeNthFromEnd(ListNode head, int n) {
            ListNode dummy = new ListNode(0);
            dummy.next = head;
            ListNode p = dummy;
            ListNode q = dummy;
            for (int i = 0; i <= n; i++) {
                q = q.next;
            }
            while (q != null) {
                p = p.next;
                q = q.next;
            }
            p.next = p.next.next;
            return dummy.next;
       }

    leetcode 21. 合并两个有序链表

    将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

    示例:

    输入:1->2->4, 1->3->4
    输出:1->1->2->3->4->4

    class Solution {
        public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
            ListNode node = new ListNode(0);
            ListNode pre = node;
            while(l1 != null && l2 != null){
                if(l1.val <= l2.val){
                    pre.next = l1;
                    l1 = l1.next;
                }
                else{
                    pre.next = l2;
                    l2 = l2.next;
                }
                pre = pre.next;
            }
            pre.next = l1 == null? l2:l1;
            return node.next;
        }
    }
  • 相关阅读:
    所有抽样单元都有相等的被选取机会 ,说法错误
    银行存款余额表由谁编制的
    资本公积——资本溢价与资本公积——其他资本公积
    货币单元抽祥
    企业安全生产费用账务的处理
    Tableau代写制作地图可视化和树形图、条形图
    Tableau 代写数据可视化:探索性图形分析新生儿死亡率数据
    R、Python代写、Open Refine采集pdf数据,清理数据和格式化数据
    使用GIS编程代写制作静态地图和处理地理数据
    用R语言编程代写制作交互式图表和地图
  • 原文地址:https://www.cnblogs.com/lyuzt/p/11962759.html
Copyright © 2020-2023  润新知