• leetcode: 链表2


    1. 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.

    深拷贝一个链表,链表除了含有next指针外,还包含一个random指针,该指针指向字符串中的某个节点或者为空

    假设原始链表如下,细线表示next指针,粗线表示random指针,没有画出的指针均指向NULL:

    原链表

    构建新节点时,指针做如下变化,即把新节点插入到相应的旧节点后面:

    新结点插入到原结点之后

    /**
     * Definition for singly-linked list with a random pointer.
     * class RandomListNode {
     *     int label;
     *     RandomListNode next, random;
     *     RandomListNode(int x) { this.label = x; }
     * };
     */
    public class Solution {  
        public RandomListNode copyRandomList(RandomListNode head) {  
            if (head == null) return null;  
              
            //第一遍扫描:对每个结点进行复制,把复制出来的新结点插在原结点之后  
            RandomListNode node = head;  
            while (node != null) {  
                RandomListNode newnode = new RandomListNode(node.label);  
                newnode.next = node.next;  
                node.next = newnode;  
                node = newnode.next;  
            }  
              
            //第二遍扫描:根据原结点的random,给新结点的random赋值  
            node = head;  
            while (node != null) {  
                if (node.random != null) node.next.random = node.random.next;  
                node = node.next.next;  
            }  
              
            RandomListNode newhead = head.next;  
              
            //第三遍扫描:把新结点从原链表中拆分出来  
            node = head;  
            while (node != null) {  
                RandomListNode newnode = node.next;  
                node.next = newnode.next;  
                if (newnode.next != null) newnode.next = newnode.next.next;  
                node = node.next;  
            }  
              
            return newhead;  
        }  
    }  
    

      

    # Definition for singly-linked list with a random pointer.
    # class RandomListNode:
    #     def __init__(self, x):
    #         self.label = x
    #         self.next = None
    #         self.random = None
    
    class Solution:
        # @param head, a RandomListNode
        # @return a RandomListNode
        def copyRandomList(self, head):
            if head == None: return None
            tmp = head
            while tmp:
                newNode = RandomListNode(tmp.label)
                newNode.next = tmp.next
                tmp.next = newNode
                tmp = tmp.next.next
            tmp = head
            while tmp:
                if tmp.random:
                    tmp.next.random = tmp.random.next
                tmp = tmp.next.next
            newhead = head.next
            pold = head
            pnew = newhead
            while pnew.next:
                pold.next = pnew.next
                pold = pold.next
                pnew.next = pold.next
                pnew = pnew.next
            pold.next = None
            pnew.next = None
            return newhead

    2. convert-sorted-list-to-binary-search-tree(有序链表转为二叉搜索树)

    Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.

    从给定的有序链表生成二叉搜索树。

    如果链表是空的,那么构造出来的BST也是空的。

    如果链表只有一个节点,那么构造出来的BST也只有一个节点。

    如果链表有两个或更多节点,那就找出中间的节点,用它构造根节点。它左边的链表构造左子树,右边的链表构造右子树。

      /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; next = null; }
     * }
     */
    /**
     * Definition for binary tree
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
      
      
     public class Solution { 
     
        public static TreeNode sortedListToBST(ListNode head) {  
            return rec(head, null);  
        }  
           
        // 在区间[start, end)里递归,后面的end是包括在内的,这样可以避免要多用一个指针来记录mid前的节点  
        public static TreeNode rec(ListNode start, ListNode end){  
            if(start == end){  
                return null;  
            }  
               
            // 一次遍历找到中点的方法:快慢指针  
            ListNode mid = start;           // 该指针最终会指向中点  
            ListNode probe = start;         // 探针最终会到达end  
            while(probe!=end && probe.next!=end){       // 探针完成搜索,注意停止条件是和end比较而不是和null比!  
                mid = mid.next;  
                probe = probe.next.next;  
            }  
               
            TreeNode root = new TreeNode(mid.val);  
            
            root.left = rec(start, mid);  
            root.right = rec(mid.next, end);  
            
            return root;  
        }  
       
    }    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; next = null; }
     * }
     */
    /**
     * Definition for binary tree
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
      
      
     public class Solution { 
     
        public static TreeNode sortedListToBST(ListNode head) {  
            return rec(head, null);  
        }  
           
        // 在区间[start, end)里递归,后面的end是包括在内的,这样可以避免要多用一个指针来记录mid前的节点  
        public static TreeNode rec(ListNode start, ListNode end){  
            if(start == end){  
                return null;  
            }  
               
            // 一次遍历找到中点的方法:快慢指针  
            ListNode mid = start;           // 该指针最终会指向中点  
            ListNode probe = start;         // 探针最终会到达end  
            while(probe!=end && probe.next!=end){       // 探针完成搜索,注意停止条件是和end比较而不是和null比!  
                mid = mid.next;  
                probe = probe.next.next;  
            }  
               
            TreeNode root = new TreeNode(mid.val);  
            
            root.left = rec(start, mid);  
            root.right = rec(mid.next, end);  
            
            return root;  
        }  
       
    }  
    View Code
    # Definition for a  binary tree node
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    #
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        # @param head, a list node
        # @return a tree node
        def sortedArrayToBST(self, array):
            length = len(array)
            if length==0: return None
            if length==1: return TreeNode(array[0])
            root = TreeNode(array[length/2])
            root.left = self.sortedArrayToBST(array[:length/2])
            root.right = self.sortedArrayToBST(array[length/2+1:])
            return root
            
        def sortedListToBST(self, head):
            array = []
            p = head
            while p:
                array.append(p.val)
                p = p.next
            return self.sortedArrayToBST(array)

    3. merge two sorted lists  (合并两个排好序的链表)

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

    合并两个排序链表并返回一个新的链表,新的链表的结果由原先的两个链表结点组成,也就是合并后的链表不能包含新创建的结点

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    public class Solution {
        public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
     
            ListNode p1 = l1;
            ListNode p2 = l2;
     
            ListNode fakeHead = new ListNode(0);
            ListNode p = fakeHead;
     
            while(p1 != null && p2 != null){
              if(p1.val <= p2.val){
                  p.next = p1;
                  p1 = p1.next;
              }else{
                  p.next = p2;
                  p2 = p2.next;
              }
     
              p = p.next;
            }
     
            if(p1 != null)
                p.next = p1;
            if(p2 != null)
                p.next = p2;
     
            return fakeHead.next;
        }
    }
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        # @param two ListNodes
        # @return a ListNode
        def mergeTwoLists(self, l1, l2):
            if l1 == None:
                return l2
            if l2 == None:
                return l1
            dummy = ListNode(0)
            tmp = dummy
            while l1 and l2:
                if l1.val <= l2.val:
                    tmp.next = l1
                    l1 = l1.next
                    tmp = tmp.next
                else:
                    tmp.next = l2
                    l2 = l2.next
                    tmp = tmp.next
            if l2 == None:
                tmp.next = l1
            else:
                tmp.next = l2
            return dummy.next

    4.  sort list(链表排序)

    Sort a linked list in O(n log n) time using constant space complexity.

      /*
             * 实现链表的合并排序:1、将链表划分成基本相等的两个链表
             * 2、递归将这两个链接继续划分,直到链表的长度为0或者1为止
             * 3、调用Merge()将链接进行合并
      */
    /**
     * Definition for singly-linked list.
     * class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    public class Solution {
            public static  ListNode sortList(ListNode head) {
            if(head == null || head.next == null) return head;
            ListNode slow = head;
            ListNode fast = head;
            while(fast.next != null && fast.next.next != null){
                slow = slow.next;
                fast = fast.next.next;
            }
            ListNode list2 = slow.next;
            slow.next = null;
            head = sortList(head);
            list2 = sortList(list2);
            return merge(head, list2);
        }
        
        private static ListNode merge(ListNode list1, ListNode list2) {
            if(list1 == null) return list2;
            if(list2 == null) return list1;
            ListNode newHead = new ListNode(0);
            ListNode last = newHead;
            last = newHead;
            while(list1 != null && list2 != null){
                if(list1.val < list2.val){
                    last.next = list1;
                    list1 = list1.next;
                }else{
                    last.next = list2;
                    list2 = list2.next;
                }
                last = last.next;
            }
            if(list1 != null) last.next = list1;
            else if(list2 != null) last.next = list2;
            return newHead.next;
        }
    }
    View Code

    题意:链表的排序。要求:时间复杂度O(nlogn),空间复杂度O(1)。

    解题思路:由于题目对时间复杂度和空间复杂度要求比较高,所以查看了各种解法,最好的解法就是归并排序,由于链表在归并操作时并不需要像数组的归并操作那样分配一个临时数组空间,所以这样就是常数空间复杂度了,当然这里不考虑递归所产生的系统调用的栈。

           这里涉及到一个链表常用的操作,即快慢指针的技巧。设置slow和fast指针,开始它们都指向表头,fast每次走两步,slow每次走一步,fast到链表尾部时,slow正好到中间,这样就将链表截为两段。

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        # @param head, a ListNode
        # @return a ListNode
        def merge(self, head1, head2):
            if head1 == None: return head2
            if head2 == None: return head1
            dummy = ListNode(0)                             #归并时,新建一个链表头结点
            p = dummy
            while head1 and head2:
                if head1.val <= head2.val:
                    p.next = head1
                    head1 = head1.next
                    p = p.next
                else:
                    p.next = head2
                    head2 = head2.next
                    p = p.next
            if head1 == None:
                p.next = head2
            if head2 == None:
                p.next = head1
            return dummy.next
            
        def sortList(self, head):
            if head == None or head.next == None:
                return head
            slow = head; fast = head                        #快慢指针技巧的运用,用来截断链表。
            while fast.next and fast.next.next:
                slow = slow.next
                fast = fast.next.next
            head1 = head
            head2 = slow.next
            slow.next = None                                #head1和head2为截为两条链表的表头
            head1 = self.sortList(head1)
            head2 = self.sortList(head2)
            head = self.merge(head1, head2)
            return head

    5. reorder list(重排链表)

    Given a singly linked list L: L0→L1→…→Ln-1→Ln,
    reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…

    You must do this in-place without altering the nodes' values.

    For example,
    Given {1,2,3,4}, reorder it to {1,4,2,3}.

    给定一个链表,把最后一个结点插入到第1个结点后,倒数第二个结点插入到第2个结点后,倒数第三个结点插入到第3个结点后,以此类推……

    由题意知,后面 (n-1)/2 个结点需要分别插入到前面 (n-1)/2 个结点后。

    那么先把链表分为两段,前面 n-(n-1)/2 个结点为被插入链表,和后面 (n-1)/2 个结点为插入链表。

    在插入之前,需先把插入链表逆序,即第n个结点->第n-1个结点->...

    public class Solution {  
        public void reorderList(ListNode head) {  
            ListNode node = head;  
            int cnt = 0;  
            while (node != null) {  
                cnt++;  
                node = node.next;  
            }  
              
            if (cnt < 3) return;//3个以下的结点不需要移动  
              
            int k = (cnt - 1) / 2;//需要移动的后k个结点  
            int i = 1;  
            node = head;  
            while (i++ < cnt - k) {  
                node = node.next;  
            }  
            ListNode begin = node.next;//用begin表示需要移动的后k个结点的开始  
            node.next = null;//把不需要移动的部分结尾设为null  
              
            //把需要移动的k个结点逆序  
            ListNode pre = begin;  
            ListNode cur = begin.next;  
            begin.next = null;  
            while (cur != null) {  
                ListNode next = cur.next;  
                cur.next = pre;  
                  
                begin = cur;  
                pre = cur;  
                cur = next;  
            }  
              
            ListNode node1 = head;  
            ListNode node2 = begin;  
            while (node1 != null && node2 != null) {  
                pre = node1;  
                cur = node2;  
                  
                node1 = node1.next;//这两行一定要放在下面两行之前,因为pre和node1指向同一个结点,下面操作会改变node1的next;cur和node2同理  
                node2 = node2.next;  
                  
                cur.next = pre.next;//这两行代码是把cur插入到pre后  
                pre.next = cur;  
            }  
        }  
    }  
    View Code

    解题思路:1,先将链表截断为两个相等长度的链表,如果链表长度为奇数,则第一条链表长度多1。如原链表为L={1,2,3,4,5},那么拆分结果为L1={1,2,3};L2={4,5}。拆分的技巧还是快慢指针的技巧。

           2,将第二条链表L2翻转,如将L2={4,5}翻转为L2={5,4}。

                  3,按照题意归并链表。

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        # @param head, a ListNode
        # @return nothing
        def reorderList(self, head):
            if head==None or head.next==None or head.next.next==None: return head
            
            # break linked list into two equal length
            slow = fast = head                              #快慢指针技巧
            while fast and fast.next:                       #需要熟练掌握
                slow = slow.next                            #链表操作中常用
                fast = fast.next.next
            head1 = head
            head2 = slow.next
            slow.next = None
    
            # reverse linked list head2
            dummy=ListNode(0); dummy.next=head2             #翻转前加一个头结点
            p=head2.next; head2.next=None                   #将p指向的节点一个一个插入到dummy后面
            while p:                                        #就完成了链表的翻转
                tmp=p; p=p.next                             #运行时注意去掉中文注释
                tmp.next=dummy.next
                dummy.next=tmp
            head2=dummy.next
    
            # merge two linked list head1 and head2
            p1 = head1; p2 = head2
            while p2:
                tmp1 = p1.next; tmp2 = p2.next
                p1.next = p2; p2.next = tmp1
                p1 = tmp1; p2 = tmp2

    6 linked list cycle  i  (环判断)

    Given a linked list, determine if it has a cycle in it.

    Follow up:
    Can you solve it without using extra space?

    使用快慢指针,如果有循环两指针必定能相遇:

     public boolean hasCycle(ListNode head) {
             if(head==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;
         }
    View Code
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        # @param head, a ListNode
        # @return a boolean
        def hasCycle(self, head):
            if head == None or head.next == None:
                return False
            slow = fast = head
            while fast and fast.next:
                slow = slow.next
                fast = fast.next.next
                if slow == fast:
                    return True
            return False

    7. linked list cycle ii (环的第一个节点)

    Given a linked list, return the node where the cycle begins. If there is no cycle, return  null .

    Follow up:

    Can you solve it without using extra space?

    一个快指针,一个慢指针,同点出发,如果快的走到null说明没循环,否则两指针必定相遇在一点。

    然后把慢指针吊回head, 快指针与慢指针同步同速率前进,直到相遇,相遇点即为循环开始点。

    原理证明:

    假设头节点到循环开始节点距离为x

    循环长度:y

    快指针一次两步慢指针一次一步

    假设相遇点为m(距离循环开始点m距离),m必定在循环内部。

    快指针移动路程: x + ky + m 慢指针移动路程: x + ty + m

    x+ky+m = 2(x+ty+m)

    => ky = 2ty + x + m => (x + m) mod y = 0

    所以快指针再跑x距离就能到达循环开始点。

     1 public ListNode detectCycle(ListNode head) {
     2         if(head==null || head.next==null)
     3             return null;
     4         ListNode slow=head;
     5         ListNode fast=head;
     6         while(true)
     7         {
     8             slow=slow.next;
     9             if(fast==null || fast.next==null)
    10                 return null;
    11             fast=fast.next.next;
    12             if(slow==fast)
    13                 break;
    14         }
    15         slow=head;
    16         while(slow!=fast)
    17         {
    18             slow=slow.next;
    19             fast=fast.next;
    20         }
    21         return slow;
    22     }
    View Code
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        # @param head, a ListNode
        # @return a list node
        def detectCycle(self, head):
            if head == None or head.next == None:
                return None
            slow = fast = head
            while fast and fast.next:
                slow = slow.next
                fast = fast.next.next
                if fast == slow:
                    break
            if slow == fast:
                slow = head
                while slow != fast:
                    slow = slow.next
                    fast = fast.next
                return slow
            return None

    8. remove-duplicates-from-sorted-list i (重复节点)

    Given a sorted linked list, delete all duplicates such that each element appear only once.

    For example,
    Given1->1->2, return1->2.
    Given1->1->2->3->3, return1->2->3.

    public class Solution {
        public ListNode deleteDuplicates(ListNode head) {
            if(head == null || head.next == null)
                return head;
     
            ListNode p = head;
     
            while( p!= null && p.next != null){
                if(p.val == p.next.val){
                    p.next = p.next.next;
                }else{
                    p = p.next; 
                }
            }
     
            return head;
        }
    }
    View Code
    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    public class Solution {
        public ListNode deleteDuplicates(ListNode head) {
            if(head == null || head.next == null)
                return head;
     
            ListNode prev = head;    
            ListNode p = head.next;
     
            while(p != null){
                if(p.val == prev.val){
                    prev.next = p.next;
                    p = p.next;
                    //no change prev
                }else{
                    prev = p;
                    p = p.next; 
                }
            }
     
            return head;
        }
    }
    View Code
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        # @param head, a ListNode
        # @return a ListNode
        def deleteDuplicates(self, head):
            if head == None or head.next == None:
                return head
            p = head
            while p.next:
                if p.val == p.next.val:
                    p.next = p.next.next
                else:
                    p = p.next
            return head
    View Code

    9.remove-duplicates-from-sorted-list ii(重复节点)

    Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinctnumbers from the original list.

    For example,
    Given1->2->3->3->4->4->5, return1->2->5.
    Given1->1->1->2->3, return2->3.

    public ListNode deleteDuplicates(ListNode head) {
        ListNode t = new ListNode(0);
        t.next = head;
     
        ListNode p = t;
        while(p.next!=null&&p.next.next!=null){
            if(p.next.val == p.next.next.val){
                int dup = p.next.val;
                while(p.next!=null&&p.next.val==dup){
                    p.next = p.next.next;
                }
            }else{
                p=p.next;
            }
     
        }
     
        return t.next;
    }
    View Code
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        # @param head, a ListNode
        # @return a ListNode
        def deleteDuplicates(self, head):
            if head == None or head.next == None:
                return head
            dummy = ListNode(0); dummy.next = head
            p = dummy
            tmp = dummy.next
            while p.next:
                while tmp.next and tmp.next.val == p.next.val:
                    tmp = tmp.next
                if tmp == p.next:
                    p = p.next
                    tmp = p.next
                else:
                    p.next = tmp.next
            return dummy.next

     

     
  • 相关阅读:
    Error-Project facet Java version 1.8 is not supported
    如何运行Struts2官网最新Demo?
    Java计算两个字符串日期之间的天数差
    Mybatis XML配置
    使用本地缓存快还是使用redis缓存好?
    mysql数据统计技巧备忘录
    java中的全局变量如何实现?ThreadLocal~
    干货!一次kafka卡顿事故排查过程
    《Java 多线程编程核心技术》- 笔记
    《分布式服务框架原理与实践》- 总结一下吧
  • 原文地址:https://www.cnblogs.com/zxqstrong/p/5386393.html
Copyright © 2020-2023  润新知