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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/zxqstrong/p/5386393.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值