【LEETCODE】64、鏈表分類,medium&hard級別,題目:2,138,142,23

package y2019.Algorithm.LinkedList.medium;

import y2019.Algorithm.LinkedList.ListNode;

/**
 * @ProjectName: cutter-point
 * @Package: y2019.Algorithm.LinkedList.medium
 * @ClassName: AddTwoNumbers
 * @Author: xiaof
 * @Description: TODO 2. Add Two Numbers
 * You are given two non-empty linked lists representing two non-negative integers.
 * The digits are stored in reverse order and each of their nodes contain a single digit.
 * Add the two numbers and return it as a linked list.
 * You may assume the two numbers do not contain any leading zero, except the number 0 itself.
 *
 * Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
 * Output: 7 -> 0 -> 8
 * Explanation: 342 + 465 = 807.
 * @Date: 2019/8/1 9:06
 * @Version: 1.0
 */
public class AddTwoNumbers {

    public ListNode solution(ListNode l1, ListNode l2) {
        //兩數相加,用鏈表遍歷相加進位即可
        int increment = 0;
        ListNode p1 = l1, p2 = l2, tail1 = p1, tail2 = p2;
        while (p1 != null && p2 != null) {
            int curValue = p1.val + p2.val + increment;
            increment = curValue / 10;
            curValue = curValue % 10;
            p1.val = curValue;

            tail1 = p1;
            tail2 = p2;
            p1 = p1.next;
            p2 = p2.next;
        }

        //如果l1比較長
        if (p2 == null && p1 != null) {
            //吧剩下的加入鏈表
            while (p1 != null) {
                int curValue = p1.val + increment;
                increment = curValue / 10;
                curValue = curValue % 10;
                p1.val = curValue;

                tail1 = p1;
                p1 = p1.next;
            }
        }

        if (p1 == null && p2 != null) {
            //吧剩下的加入鏈表
            while (p2 != null) {
                int curValue = p2.val + increment;
                increment = curValue / 10;
                curValue = curValue % 10;
                tail1.next = new ListNode(curValue);

                tail1 = tail1.next;
                p2 = p2.next;
            }
        }

        //最後添加increment節點
        if (increment > 0) {
            tail1.next = new ListNode(increment);
        }

        return l1;

    }

    public static void main(String[] args) {
        ListNode node1 = new ListNode();
        node1.val = 9;
        ListNode node2 = new ListNode();
        node2.val = 9;

        node1.next = node2;

        ListNode node21 = new ListNode();

        AddTwoNumbers fuc = new AddTwoNumbers();

        fuc.solution(node1, node21);

    }
}

 

package y2019.Algorithm.LinkedList.medium;

import y2019.Algorithm.LinkedList.Node;


/**
 * @ProjectName: cutter-point
 * @Package: y2019.Algorithm.LinkedList.medium
 * @ClassName: CopyRandomList
 * @Author: xiaof
 * @Description: TODO 138. Copy List with Random Pointer
 * A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
 * Return a deep copy of the list.
 *
 * Input:
 * {"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}
 *
 * Explanation:
 * Node 1's value is 1, both of its next and random pointer points to Node 2.
 * Node 2's value is 2, its next pointer points to null and its random pointer points to itself.
 *
 * 思路,參考大神操作
 * 1.首先吧鏈表複製,但是不拆開,複製出來的鏈表還是連在原來的鏈表上
 * 2.根據上一個節點是下一個節點的原始複製對象,那麼只需要吧random相應指向的節點的下一個
 * 3.拆開復制的鏈表
 * @Date: 2019/8/1 9:35
 * @Version: 1.0
 */
public class CopyRandomList {

    public Node solution(Node head) {
        if (head == null) return null;
        //開始複製
        Node p = head, p2, newHead, copy;
        //1 step
        while (p != null) {
            //新節點指向原來的下一個節點
            Node temp = new Node(p.val, p.next, p.random);
            //原來舊節點指向新節點
            p.next = temp;
            //移動到下一個舊節點
            p = temp.next;
        }

        //2 step 修改random指向
        p = head;
        while (p != null) {
            p2 = p.next;
            if(p2.random != null) {
                p2.random = p.random.next;//指向複製的節點

            }
            p = p.next.next;
        }

        //3. step拆分鏈表
        p = head;
        Node nh = new Node(), np1 = nh, np2 = np1;
        while (p != null) {
            p2 = p.next.next;

            np1 = p.next;
            np2.next = np1;
            np2 = np1;

            p.next = p2;
            p = p2;
        }

        return nh.next;

    }
}

 

package y2019.Algorithm.LinkedList.medium;

import y2019.Algorithm.LinkedList.ListNode;

import java.util.HashMap;
import java.util.Map;

/**
 * @ProjectName: cutter-point
 * @Package: y2019.Algorithm.LinkedList.medium
 * @ClassName: DetectCycle
 * @Author: xiaof
 * @Description: TODO 142. Linked List Cycle II
 * Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
 * To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked
 * list where tail connects to. If pos is -1, then there is no cycle in the linked list.
 *
 * Input: head = [3,2,0,-4], pos = 1
 * Output: tail connects to node index 1
 * Explanation: There is a cycle in the linked list, where tail connects to the second node.
 * @Date: 2019/8/1 8:57
 * @Version: 1.0
 */
public class DetectCycle {

    public ListNode solution(ListNode head) {

        //針對有換問題,可以考慮用set,或者用2個指針,如果要找位置的話,感覺hashmap可能更好
        Map nodeMap = new HashMap();
        ListNode res = null, p = head;
        int index = 0;
        //遍歷鏈表,直到遇到重複
        while (p != null) {
            //遍歷獲取下一個數據
            if(nodeMap.containsKey(p)) {
                //如果已經存在
                res = p;
                break;
            } else {
                //如果不包含
                nodeMap.put(p, index++);
                p = p.next;
            }
        }

        return res;
    }
}

 

package y2019.Algorithm.LinkedList.hard;

import y2019.Algorithm.LinkedList.ListNode;

/**
 * @ProjectName: cutter-point
 * @Package: y2019.Algorithm.LinkedList.hard
 * @ClassName: MergeKLists
 * @Author: xiaof
 * @Description: 23. Merge k Sorted Lists
 * Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
 * Input:
 * [
 *   1->4->5,
 *   1->3->4,
 *   2->6
 * ]
 * Output: 1->1->2->3->4->4->5->6
 *
 * 參考: 148. Sort List的解法
 * @Date: 2019/8/1 10:28
 * @Version: 1.0
 */
public class MergeKLists {

    public ListNode mergeKLists(ListNode[] lists) {
        //多鏈表合併,可以簡化爲多個雙鏈表合併,做循環即可
        if (lists == null || lists.length == 0) {
            return null;
        }

        if (lists.length == 1) {
            return lists[0];
        }
        //1,先取一個數組,然後循環遍歷所有數組跟之前的數組做merge
        ListNode res = lists[0];
        for(int i = 1; i < lists.length; ++i) {
            res = merge(res, lists[i]);
        }

        return res;
    }

    ListNode merge(ListNode l1, ListNode l2) {

        if(l1 == null && l2 == null) {
            return null;
        } else if (l1 == null) {
            return l2;
        } else if (l2 == null) {
            return l1;
        }

        //合併倆個鏈表
        ListNode newl = new ListNode(0);

        //遍歷兩個鏈表,獲取對應的位置添加到鏈表
        //1。老規矩,獲取前一個鏈表位置,後一個位置,當前位置
        ListNode addl = newl, l1next = l1.next, l2next = l2.next, temp;
        //2.吧需要添加進去的鏈表後面加上當前節點
        while (l1 != null && l2 != null) {
            //3.把當前節點的下一個索引斷開
            if(l1.val < l2.val) {
                //如果是必第二個鏈表的小,那麼我們用第一個鏈表
                addl.next = l1;
                temp = l1.next;
                l1.next = null;
                l1 = temp;
            } else {
                addl.next = l2;
                temp = l2.next;
                l2.next = null;
                l2 = temp;
            }
            //4.吧當前索引指向下一個節點
            addl = addl.next;
        }



        //5.最後吧剩餘的節點直接加入到新鏈表中
        if(l1 != null) {
            addl.next = l1;
        }

        if(l2 != null) {
            addl.next = l2;
        }

        return newl.next;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章