显示标签为“linkedlist”的博文。显示所有博文
显示标签为“linkedlist”的博文。显示所有博文

2015年12月18日星期五

Remove Linked List Elements leetcode

Remove all elements from a linked list of integers that have value val.
Example
Given: 1 --> 2 --> 6 --> 3 --> 4 --> 5 --> 6, val = 6
Return: 1 --> 2 --> 3 --> 4 --> 5
public class Solution {
    public ListNode removeElements(ListNode head, int val) {
        if (head == null) {
            return head;
        }
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode node = dummy;
        while (node.next != null) {
            if (node.next.val == val) {
                node.next = node.next.next;
            } else {
                node = node.next;
            }
        }
        return dummy.next;
    }
}

2015年10月26日星期一

Delete Node in a Linked List leetcode

Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.

题意:

编写一个函数删除单链表中(除末尾节点外)的一个节点,只提供待删除节点。

假如链表是1 -> 2 -> 3 -> 4 给你第3个节点,值为3,则调用你的函数后链表为1 -> 2 -> 4

public class Solution {
    public void deleteNode(ListNode node) {
        node.val = node.next.val;
        node.next = node.next.next;
    }
}

Palindrome Linked List leetcode

Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
找到list的中点, 然后翻转后面的list 一一对比

public class Solution {
    public boolean isPalindrome(ListNode head) {
        if (head == null || head.next == null) {
            return true;
        }
        ListNode fast = head, slow = head;
        while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode cur = reverse(slow.next);// 这里导入的是中点的下一个 因为这种找中点情况 偶数时候是在左中点, 奇数时候是在正中点
        while (cur != null) {////这里不能是head!=null 对于0->0这个list head后面还有一个元素0

            if (head.val != cur.val) {
                return false;
            }
            head = head.next;
            cur = cur.next;
        }
        return true;
    }
    public ListNode reverse(ListNode node) {
        ListNode dummy = new ListNode(0);
        dummy.next = node;
        ListNode next = node.next;
        while (next != null) {
            node.next = next.next;
            next.next = dummy.next;
            dummy.next = next;
            next = node.next;
        }
        return dummy.next;
    
    }
}

2015年10月13日星期二

Intersection of Two Linked Lists leetcode

Write a program to find the node at which the intersection of two singly linked lists begins.

For example, the following two linked lists:
A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3
begin to intersect at node c1.

Notes:


  • If the two linked lists have no intersection at all, return null.
  • The linked lists must retain their original structure after the function returns.
  • You may assume there are no cycles anywhere in the entire linked structure.
  • Your code should preferably run in O(n) time and use only O(1) memory.
首先找到两条链表的长度, 然后截取相同的长度, 从两个开端一起走 碰到一起的话返回碰到时候的node, 没有相遇的话返回null.

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int lena = getlen(headA);
        int lenb = getlen(headB);
        ListNode nodea = headA;
        ListNode nodeb = headB;
        if (lena > lenb) {
            for (int i = 0; i < lena - lenb; i++) {
                nodea = nodea.next;
            }
        } else {
            for (int i = 0; i < lenb - lena; i++) {
                nodeb = nodeb.next;
            }
        }
        while (nodea != null && nodeb!= null) {
            if (nodea == nodeb) {
                return nodea;
            }
            nodea = nodea.next;
            nodeb = nodeb.next;
        }
        return null;
    }
    public int getlen(ListNode head) {
        int count = 0;
        while (head != null) {
            head = head.next;
            count++;
        }
        return count;
    } 
}

2015年7月26日星期日

Remove Duplicates from Sorted List II leetcode

Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3.
因为表头可能被删除, 创建一个dummy node, 令dummynode.next = head, return dummy.next
时间O(n) 空间O(1)
 
public class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode cur = head;
        ListNode pre = dummy;
        while (cur != null && cur.next != null) {
            if (cur.val == cur.next.val) {
                int val = cur.val;
                while (cur != null && cur.val == val) {
                    cur = cur.next;
                }
                pre.next = cur;
            } else {
                pre = pre.next;
                cur = cur.next;
            }
        }
        return dummy.next;
    }
}
public class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if (head == null || head.next == null){
            return head;
        }
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        head = dummy;
        while (head.next != null && head.next.next != null){
            if (head.next.val == head.next.next.val){
                int val = head.next.val;
                while (head.next != null && head.next.val == val){
                    head.next = head.next.next;
                }
            } else {//注意一定要在else语句里head往下传递 否则会溢出
                head = head.next;
            }
        }
        return dummy.next;
    }
}

2015年7月25日星期六

链表总结

链表的基本形式是:1 -> 2 -> 3 -> null,反转需要变为 3 -> 2 -> 1 -> null。

  • 访问某个节点 curt.next 时,要检验 curt 是否为 null。 
  • 要把反转后的最后一个节点(即反转前的第一个节点)指向 null。

public ListNode reverse(ListNode head) {
    ListNode prev = null;
    while (head != null) {
        ListNode next = head.next;
        head.next = prev;
        prev = head;
        head = next;
    }
    return prev;
}




1 -> 2 -> 3 -> 4 -> 5 -> 6 -> null变为 1 -> 5 -> 4 -> 3 -> 2 -> 6 -> null
翻转m--n, 不仅要把m-n转好, preMnode. next 要指向n, m.next 要指向postNnode

public class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        if (m > n || head == null){
            return head;
        }
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        head = dummy;
        for (int i = 1; i < m; i++){
            head = head.next;
        }
        ListNode preM = head;
        ListNode mNode = head.next;
        ListNode nNode = mNode;
        ListNode postN = mNode.next;
        for (int i = m; i < n; i++){
            ListNode tem = postN.next;
            postN.next = nNode;
            nNode = postN;
            postN = tem;
        }
        preM.next = nNode;
        mNode.next = postN;
        return dummy.next;
    }
}

删除链表中的某个节点 

删除链表中的某个节点一定需要知道这个点的前继节点,所以需要一直有指针指向前继节点。
然后只需要把 prev -> next = prev -> next -> next 即可。但是由于链表表头可能在这个过程中产生变化,导致我们需要一些特别的技巧去处理这种情况。就是下面提到的 Dummy Node。

找中点

        ListNode fast = head;
        ListNode slow = head;
        while (fast!= null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }


链表指针的鲁棒性

综合上面讨论的两种基本操作,链表操作时的鲁棒性问题主要包含两个情况:
  • 当访问链表中某个节点 curt.next 时,一定要先判断 curt 是否为 null。
  • 全部操作结束后,判断是否有环;若有环,则置其中一端为 null。

Dummy Node


Dummy node 是一个虚拟节点,也可以认为是标杆节点。Dummy node 就是在链表表头 head 前加一个节点指向 head,即 dummy -> head。Dummy node 的使用多针对单链表没有前向指针的问题,保证链表的 head 不会在删除操作中丢失。除此之外,还有一种用法比较少见,就是使用 dummy node 来进行head的删除操作,比如 Remove Duplicates From Sorted List II,一般的方法current = current.next 是无法删除 head 元素的,所以这个时候如果有一个dummy node在head的前面。
所以,当链表的 head 有可能变化(被修改或者被删除)时,使用 dummy node 可以很好的简化代码,最终返回 dummy.next 即新的链表。

快慢指针

快慢指针也是一个可以用于很多问题的技巧。所谓快慢指针中的快慢指的是指针向前移动的步长,每次移动的步长较大即为快,步长较小即为慢,常用的快慢指针一般是在单链表中让快指针每次向前移动2,慢指针则每次向前移动1。快慢两个指针都从链表头开始遍历,于是快指针到达链表末尾的时候慢指针刚好到达中间位置,于是可以得到中间元素的值。快慢指针在链表相关问题中主要有两个应用:
  • 快速找出未知长度单链表的中间节点 设置两个指针 *fast*slow 都指向单链表的头节点,其中*fast的移动速度是*slow的2倍,当*fast指向末尾节点的时候,slow正好就在中间了。
  • 判断单链表是否有环 利用快慢指针的原理,同样设置两个指针 *fast*slow 都指向单链表的头节点,其中 *fast的移动速度是*slow的2倍。如果 *fast = NULL,说明该单链表 以 NULL结尾,不是循环链表;如果 *fast = *slow,则快指针追上慢指针,说明该链表是循环链表。


Remove Duplicates from Sorted List

Remove Duplicates from Sorted ListII



Reorder List

Merge k Sorted Lists

Remove Nth Node From End of List

List Cycle

Linked List Cycle II


Reverse Nodes in k-Group

Rotate List

Insertion Sort List

2015年6月11日星期四

Convert Sorted List to Binary Search Tree leetcode

因为链表和array不同, 不能直接访问中间元素.
中序遍历,按照递归中序遍历的顺序对链表结点一个个进行访问,而我们要构造的二分查找树正是按照链表的顺序来的。
思路就是先对左子树进行递归,然后将当前结点作为根,迭代到下一个链表结点,最后在递归求出右子树即可。
因为listnode不能传递 所以要放入一个arraylist中
整体过程就是一次中序遍历,时间复杂度是O(n),总的空间复杂度是栈空间O(logn)。

 */
public class Solution {
    public TreeNode sortedListToBST(ListNode head) {
        if (head == null) {
            return null;
        }
        ArrayList<ListNode> res = new ArrayList<ListNode>();
        res.add(head);
        ListNode cur = head;
        int count = 0;
        while (cur != null) {
            cur = cur.next;
            count++;//找出链表的总个数
        }
        return helper(res, 0, count - 1);
    }
    public TreeNode helper(ArrayList<ListNode> res, int start, int end) {
        if (start > end) {
            return null;
        }
        int mid = (end + start) / 2;
        TreeNode left = helper(res, start, mid - 1);
        TreeNode root = new TreeNode(res.get(0).val);
        root.left = left;
        res.set(0, res.get(0).next);//指向链表的下一个元素 因为中序遍历 下一个要访问的点就是该点
        root.right = helper(res, mid + 1, end);
        return root;
    }
}

第二种做法是把list存在一个hashmap里面, 然后向做arry那样的递归做, 时间复杂O(n), 空间O(n)

public class Solution {
    /**
     * @param head: The first node of linked list.
     * @return: a tree node
     */
    public TreeNode sortedListToBST(ListNode head) {  
        if (head == null) {
            return null;
        }
        HashMap map = new HashMap();
        int i = 0;
        while (head != null) {
            map.put(i, head);
            i++;
            head = head.next;
        }
        return helper(0, i - 1, map);
    }
    public TreeNode helper(int start, int end, HashMap map) {
        if (start > end) {
            return null;
        }
        int mid = (start + end) / 2;
        ListNode node = map.get(mid);
        TreeNode head = new TreeNode(node.val);
        head.left = helper(start, mid - 1, map);
        head.right = helper(mid + 1, end, map);
        return head;
    }
}



2015年6月2日星期二

Insertion Sort List leetcode

Example
Given 1->3->2->0->null, return 0->1->2->3->null.
把一个个的listnode往新的排序里面插, 维护两个指针cur(原链表) node(新链表).
node始终指向新链表表头 每次插入时候遍历新链表 往后找到node.val < cur.val 中最后一个 插入cur.(新链表升序排列 后面的val比前边大)

时间复杂度是排序算法的O(n^2),空间复杂度O(1)
public class Solution {
    public ListNode insertionSortList(ListNode head) {
        if (head == null) {
            return head;
        }
        ListNode dummy = new ListNode(0);
        ListNode cur = head;
        while (cur != null) {
            ListNode node = dummy;
            while (node.next != null && node.next.val < cur.val) {//node是升序排列的 node.next > node
                node = node.next;
            }
            ListNode tem = cur.next;
            cur.next = node.next;
            node.next = cur;
            cur = tem;
        }
        return dummy.next;
    }
}

Rotate List leetcode

Given a list, rotate the list to the right by k places, where k is non-negative.
For example:
Given 1->2->3->4->5->NULL and k = 2,
return 4->5->1->2->3->NULL.
k的值可以大于链表长度, 大于的话用k对length取莫. 用快慢指针方法 快指针先走k步 然后一起走.
 最后快指针停在最后面的位置 (null之前),慢指针停在要翻转的前一个位置.
记录slow.next就是newhead结点, fast,next 指向原来的head, slow.next指向null

public class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if (k == 0 || head == null) {
            return head;
        }
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode fast = head;
        ListNode slow = head;
        ListNode cur = head;
        int len = 0;
        while (cur != null) {
            cur = cur.next;
            len++;
        }
        k = k%len;
        for (int i = 0; i < k; i++) {
            fast = fast.next;
        }
        while (fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        fast.next = head;
        dummy.next = slow.next;
        slow.next = null;
        return dummy.next;
    }
    
}

2015年6月1日星期一

Reverse Nodes in k-Group leetcode

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
You may not alter the values in the nodes, only nodes itself may be changed.
Only constant memory is allowed.
For example,
Given this linked list: 1->2->3->4->5
For k = 2, you should return: 2->1->4->3->5
For k = 3, you should return: 3->2->1->4->5 
先统计目前节点的数量,达到k就把当前k个结点翻转。遍历linkedlist 当到达k的时候翻转,所以总体来说每个结点会被访问两次。总时间复杂度是O(2*n)=O(n),空间复杂度是O(1)。
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if (k == 0 || k == 1) {
            return head;
        }
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        int count = 0;
        ListNode pre = dummy;
        ListNode cur = head;
        while (cur != null) {
            count++;
            cur = cur.next;
            if (count == k) {
                pre = reverse(pre,cur);//pre 变成翻转链表后的最后一个node, 此处翻转pre和cur中间的点
                count = 0;
            }
        }
        return dummy.next;
    }
    public ListNode reverse(ListNode pre, ListNode next) {
        ListNode last = pre.next;
        ListNode cur = pre.next.next;
        while (cur != next) {
            last.next = cur.next;
            cur.next = pre.next;
            pre.next = cur;
            cur = last.next;
        }
        return last;
    }
}

Swap Nodes in Pairs leetcode

Given a linked list, swap every two adjacent nodes and return its head.
For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.
Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.
每次操作两个节点, 并且要记录两个节点前边的一个节点prev
例如1-->2-->3-->4, 对于每次循环
对于3,4 节点 把3放到4后面, 然后把prev 2 指向4, 再记录3节点为prev

时间O(n) 空间O(1)

public class Solution {
    public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode pre = dummy;
        ListNode node = head;
        while (node != null && node.next != null) {
            ListNode tem = node.next;
            node.next = node.next.next;
            tem.next = node;
            pre.next = tem;
            pre = node;
            node = node.next;
        }
        return dummy.next;
    }
}

Add Two Numbers leetcode

You are given two linked lists representing two non-negative numbers. 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.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Example
Given 7->1->6 + 5->9->2. That is, 617 + 295.
Return 2->1->9. That is 912.
Given 3->1->5 and 5->9->2, return 8->0->8.
维护一个carry用于进位 因为是反过来写的所以进位在后面 可以直接加
时间复杂度O(n)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
       if (l1 == null) {
           return l2;
       }
       if (l2 == null) {
           return l1;
       }
       int carry = 0;
       ListNode head = new ListNode(-1);
       ListNode l3 = head;
       while (l1 != null || l2 != null) {
           if (l1 != null) {
               carry += l1.val;
               l1 = l1.next;
           }
           if (l2 != null) {
               carry += l2.val;
               l2 = l2.next;
           }
           l3.next = new ListNode(carry%10);
           carry = carry/10;
           l3 = l3.next;
       }
       if (carry > 0) {
           l3.next = new ListNode(carry);
       }
       return head.next;
    }
}

2015年4月30日星期四

Linked List Cycle II leetcode

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
题解:(转自http://www.cnblogs.com/springfor/p/3862125.html) 
这个连同I都是很经典的题啦,刷CC150时候就折磨了半天。
其实就推几个递推公式就好。。首先看图(图引用自CC150):
 
从链表起始处到环入口长度为:a,从环入口到Faster和Slower相遇点长度为:x,整个环长为:c。
明确了以上信息,就可以开始做运算了。。

 假设从开始到相遇,Slower走过的路程长为s,由于Faster的步速是Slower的2倍,那么Faster在这段时间走的路程长为2s。
 而对于Faster来说,他走的路程还等于之前绕整个环跑的n圈的路程nc,加上最后这一次遇见Slower的路程s。
 所以我们有:
                   2s = nc + s 
 对于Slower来说,他走的路程长度s还等于他从链表起始处到相遇点的距离,所以有:
                    s = a + x 
 通过以上两个式子代入化简有:
                    a + x = nc
                    a = nc - x
                    a = (n-1)c + c-x
                    a = kc + (c-x)
那么可以看出,c-x,就是从相遇点继续走回到环入口的距离。上面整个式子可以看出,如果此时有个pointer1从起始点出发并且同时还有个pointer2从相遇点出发继续往前走(都只迈一步),那么绕过k圈以后, pointer2会和pointer1在环入口相遇。这样,换入口就找到了。
时间复杂度 O(n)
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null){//必须包含head.next的判定
            return null;
        }
        ListNode fast = head;
        ListNode slow = head;
        while (fast!= null && fast.next != null){//注意此处的判定
            fast = fast.next.next;
            slow = slow.next;
            if (slow == fast){
                break;
            }
        }
        if (fast != slow){
            return null;
        }
        fast = head;
        while (fast != slow){
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
        
    }
}

2015年4月29日星期三

Copy List with Random Pointer leetcode

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.
第一种方法:用hashmap
1. 把新链表和原链表按照key: value存入hashmap, 并给每个新链表附上next指针
2. 按顺序读取hashp存储的旧链表, 然后把random指针复制给新链表(必须放在hashmap读取是因为直接读取random指针就无法按顺序)
一共扫面了两次链表 时间复杂度O(n) 空间复杂度O(n)

public class Solution {
    public RandomListNode copyRandomList(RandomListNode head) {
        if (head == null){ 
            return null;
        }
        HashMap<RandomListNode, RandomListNode> map = new HashMap<RandomListNode, RandomListNode>();
        RandomListNode newhead = new RandomListNode(head.label);
        map.put(head, newhead);
        RandomListNode node = head.next;
        RandomListNode pre = newhead;
        while (node != null){
            RandomListNode tem = new RandomListNode(node.label);
            map.put(node, tem);
            pre.next = tem;
            pre = pre.next;
            node = node.next;
        }
        node = head;
        pre = newhead;
        while (node != null){
            pre.random = map.get(node.random);
            pre = pre.next;
            node = node.next;
        }
        return newhead;
        
    }
}


第二种方法:
深度拷贝一个链表

第一步:复制链表并插入原链表原链表(1->2->3->4)新链表(1->1'->2->2'->3->3'->4->4')
第二步: 改变新链表的random指针
第三步:分离连个链表
三次线性扫描,所以时间复杂度是O(n)。空间复杂度是O(1)。
public class Solution {
    public RandomListNode copyRandomList(RandomListNode head) {
        if (head == null) {
            return null;
        }
        RandomListNode node = head;
        while (node != null) {
            RandomListNode tem = new RandomListNode(node.label);
            tem.next = node.next;
            node.next = tem;
            node = node.next.next;
        }
        node = head;
        while (node != null) {
            if (node.random != null) {
                node.next.random = node.random.next;
            }
            node = node.next.next;
        }
        node = head;
        RandomListNode newhead = head.next;
        while(node != null){
            RandomListNode tem = node.next;
            node.next = tem.next;
            if (tem.next != null) {
                tem.next = tem.next.next;
            }
            node = node.next;
        }
        return newhead;
    }
}

Linked List Cycle leetcode

Given a linked list, determine if it has a cycle in it.
Follow up:
Can you solve it without using extra space?
用双指针法, 如果faster 和slower最后遇到了则有环

时间O(n) 空间O(1)
对于是否相遇的参考:转自http://www.cnblogs.com/springfor/p/3862102.html
假设Faster确实把Slower超了而且他俩还没相遇(类似Faster一下迈了2步,Slower一下迈了一步,Faster超了Slower,但是俩人并没遇上)。那么就假设Faster现在在 i+1 位置而Slower在 i 位置。那么前一时刻,Slower肯定是在 i-1 位置,而Faster肯定在(i+1)-2位置,所以前一时刻,俩人都在 i-1 位置,相遇了。
还有一种情况就是Faster在i+2位置而slower在i位置,那么前一时刻,Faster在i位置,而Slower在 i-1位置。这样问题又回归到上面那种情况了(再往前一时刻,Faster在i-2位置,Slower在i-1-1位置,相遇)。
所以,这就证明Runner和Faster在有环的链表中肯定会相遇。

public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null){
            return false;
        }
        ListNode faster = head, slower = head;
        while (faster.next != null && faster.next.next != null){
            faster = faster.next.next;
            slower = slower.next;
            if (faster == slower){
                return true;
            }
        }
        return false;
    }
}

Merge k Sorted Lists leetcode

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
用分治法的mergesort的思想 把lists分成小list 最后合并
merge的方法就是之前merge 2 sorted list的方法

时间复杂度O(nlog(n)) 计算方法用主定理


/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
  
        if (lists.length == 0 || lists == null){
            return null;
        }
        return sort(lists, 0, lists.length - 1);
    }
    private ListNode sort(ListNode[] lists, int start, int end){
        if (start == end){
            return lists[start];
        }
        int mid = (start + end) / 2;
        ListNode left = sort(lists, start, mid);
        ListNode right = sort(lists, mid + 1, end);
        return merge(left, right);
    }
    private ListNode merge(ListNode left, ListNode right){
        ListNode dummy = new ListNode(0);
        ListNode point = dummy;
        while (left != null && right != null){
            if (left.val < right.val){
                point.next = left;
                left = left.next;
            } else {
                point.next = right;
                right = right.next;
            }
            point = point.next;
        }
        if (left != null){
            point.next = left;
        } else {
            point.next = right;
        }
        return dummy.next;
    }
}

2015年4月28日星期二

Remove Nth Node From End of List leetcode

Given a linked list, remove the nth node from the end of list and return its head.
For example,
   Given linked list: 1->2->3->4->5, and n = 2.

   After removing the second node from the end, the linked list becomes 1->2->3->5.

首先先让faster从起始点往后跑n步。
然后再让slower和faster一起跑,直到faster==null时候,slower所指向的node就是需要删除的节点。
注意:慢指针要在dummy上而不是head上 因为可能head位的数值被删除
return也要return dummy.next 因为head可能被删除

时间O(n) 空间O(1)

public class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        if (n <= 0){
            return null;
        }
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode faster = head;
        ListNode slower = dummy;
        for (int i = 0; i < n; i++){
            if (faster == null){
                return null;
            }
            faster = faster.next;
        }
        while (faster!= null){
            faster = faster.next;
            slower = slower.next;
        }
        slower.next = slower.next.next;
        return dummy.next;
        
    }
}

Reorder List leetcode

Given a singly linked list LL0L1→…→Ln-1Ln,
reorder it to: L0LnL1Ln-1L2Ln-2→…
You must do this in-place without altering the nodes' values.

Example
For example,
Given 1->2->3->4->null, reorder it to 1->4->2->3->null.
第一步,将链表分为两部分。时间O(n)
第二步,将第二部分链表逆序。时间O(n)
第三步,将链表重新组合。时间O(n)
总体时间O(n) 空间O(1)

public class Solution {
    /**
     * @param head: The head of linked list.
     * @return: void
     */
    public void reorderList(ListNode head) {  
        if (head == null || head.next == null){
            return ;
        }
        ListNode mid = findmid(head);
        ListNode tail = reverse(mid.next);
        mid.next = null;
        merge(head, tail);
    }
    private ListNode findmid(ListNode head){
        ListNode slow = head;
        ListNode fast = head.next;
        while (fast.next != null && fast.next.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    private ListNode reverse(ListNode head){
        ListNode prev = null;
        while (head != null){
            ListNode tem = head.next;
            head.next = prev;
            prev = head;
            head = tem;
        }
        return prev;
    }
    private void merge(ListNode head, ListNode tail){
        ListNode dummy = new ListNode(0);
        while (head != null && tail != null){
            dummy.next = head;
            head = head.next;
            dummy = dummy.next;
            dummy.next = tail;
            tail = tail.next;
            dummy = dummy.next;
        }
        if (head != null){
            dummy.next = head;
        } else {
            dummy.next = tail;
        }
    }
}

Sort List leetcode

Sort a linked list in O(n log n) time using constant space complexity.
分析: O(nlogn)就是用merge sort或者quick sort
用merge sort首先考虑找中点---用快慢指针的方法
merge-- 用merge 2 linkedlist方法

public class Solution {
    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null){
            return head;
        }
        ListNode mid = findmid(head);
        ListNode right = sortList(mid.next);
        mid.next = null;
        ListNode left = sortList(head);
        return merge(left, right);
    }
    private ListNode findmid(ListNode head){
        ListNode slow = head;
        ListNode fast = head.next;
        while (fast.next != null && fast.next.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    private ListNode merge(ListNode head1, ListNode head2){
        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;
        while (head1 != null && head2 != null){
            if (head1.val < head2.val){
                tail.next = head1;
                tail = tail.next;
                head1 = head1.next;
            } else {
                tail.next = head2;
                tail = tail.next;
                head2 = head2.next;
            }
        }
        if (head1 != null){
            tail.next = head1;
        } else {
            tail.next = head2;
        }
        return dummy.next;
    }
}

2015年4月8日星期三

merge two sorted list leetcode

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.
Example
Given 1->3->8->11->15->null, 2->null , return 1->2->3->8->11->15->null
对于新表声明一个表头dummy 和一个指针head
然后每个list有一个指针来遍历两个list

时间O(m + n) 空间O(1)


public class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        ListNode head = dummy;
        ListNode left = l1;// 指针可以不用left 和right
        ListNode right = l2;//直接用l1, l2也可以
        while (left != null && right != null){
            if (left.val <= right.val){
                head.next = left;
                head = head.next;
                left = left.next;
            } else {
                head.next = right;
                head = head.next;
                right = right.next;
            }
        }
        if (left == null){
            head.next = right;
        }
        if (right == null){
            head.next = left;
        }
        return dummy.next;
    }
}