Leetcode刷题记

[Leetcode][LinkedList]链表相关题目汇总/分

2019-04-02  本文已影响0人  奔跑的程序媛A

目录

  1. Reverse BST
  2. Add Number
  3. Remove
  4. Sort
  5. Merge
  6. Cycle
  7. Others

A LinkedList Definition

 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }

题目详解


#206 Reverse Linked List
    public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        return help(head, null);
}
    public ListNode help(ListNode cur, ListNode pre){
        if(cur.next == null){
            cur.next = pre;
            return cur;
        }
        ListNode n = cur.next;
        cur.next = pre;
        return help(n, cur);
    }

Sol1.2 从后往前
先循环找到最后面的Node,开始处理依次翻转整个链表。处理返回翻转后的子链表

public ListNode help2(ListNode cur){
        if(cur.next == null){
            return cur;
        }
        ListNode nex = cur.next;
        ListNode res = help2(cur.next);
        nex.next = cur;
        cur.next = null;
        return res;
    }
public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        Stack<ListNode> a = new Stack<>();
        while(head.next != null){
            a.push(head);
            head = head.next;
        }
        ListNode reverse = new ListNode(head.val);
        ListNode res = reverse;
        while(!a.isEmpty()) {
            reverse.next = a.pop();
            reverse = reverse.next;
        }
        reverse.next = null;
        return res;
    }

Sol2.2 通过迭代iteration的方式
三个指针来做循环,前中后,每次改变cur指针next指向,然后移动三个指针到下一个节点

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

#92 Reverse Linked List II

Reverse a linked list from position m to n. Do it in one-pass.

public ListNode reverseBetween(ListNode head, int m, int n) {
        if(head == null || head.next == null){return head;}
        if(n == 1){return head;}
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode A = dummy;
        ListNode B = dummy.next;
        int copy_m = m;
        while(m!=1){
            A = A.next;
            B = B.next;
            m--;
        }
        //ListNode C = B.next;
        while(copy_m != n){
            if(B.next == null){break;}
            ListNode tmp = B.next.next;
            B.next.next = A.next;
            A.next = B.next;
            B.next = tmp; 
            copy_m++;
        }
        return dummy.next;
    }
public ListNode reverseBetween(ListNode head, int m, int n) {
        if(head == null || head.next == null || m >= n){return head;}
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        head = dummy;
        
        ListNode pre = head;
        for(int i = 1; i < m; i++){
            pre = pre.next;
        }
        
        ListNode tmp = pre.next;
        
        Stack<ListNode> s = new Stack<>();
        int i = 0;
        while(m+i <= n){
            s.push(tmp);
            tmp = tmp.next;
            i++;
        }
        
        ListNode post = tmp;
        
        ListNode rev = s.pop();
        tmp = rev;
        while(!s.isEmpty()){
            tmp.next = s.pop();
            tmp = tmp.next;
        }
        
        pre.next = rev;
        tmp.next = post;
        
        return dummy.next;
    }

#24 Swap Nodes in Pairs

交换链表中相邻的两个元素。

    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode tmp = dummy; //tmp==>A
        while(tmp.next!=null && tmp.next.next!=null){
            ListNode B = tmp.next;
            ListNode C = tmp.next.next;
            tmp.next = C;
            B.next = C.next;
            C.next = B;
            tmp = tmp.next.next;
        }
        return dummy.next;
    }

#25 Reverse Nodes in k-Group

将一个链表中每k个数进行翻转,末尾不足k个的数不做变化。
A->B->C->D->E,现在我们要翻转BCD三个节点。进行以下几步:
1.C->B
2.D->C
3.B->E
4.A->D
5.返回及节点B

    public ListNode reverseKGroup(ListNode head, int k) {
        if(head == null || head.next == null || k < 2) {
            return head;
        }       
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode pre = dummy;
        ListNode cur = dummy.next;
        ListNode end = cur;
        int count = 0;
        while(end != null){
            end = end.next;
            count++;
            if(count % k == 0){
                while(cur.next!=end){
                    ListNode tmp = cur.next.next;
                    cur.next.next = pre.next; //c-b
                    pre.next = cur.next;
                    cur.next = tmp;
                }
                pre = cur;
                cur = cur.next;
            }
        }
        return dummy.next;
    }

#61 Rotate List

将一个链表中的元素向右旋转k个位置。

    public ListNode rotateRight(ListNode head, int k) {
        if(head == null || k == 0) return head;
        ListNode p = head;
        int count = 1;
        while(p.next!=null){
            p = p.next;
            count++;
        }
        k = k % count;
        if(k==0){return head;}
        ListNode fast = head;
        ListNode slow = head;
        while(k!=0){
            fast = fast.next;
            k--;
        }
        while(fast.next!=null){
            slow = slow.next;
            fast = fast.next;
        }
        p.next = head;
        head = slow.next;
        slow.next = null;
        return head;
    }

#86 Partition List

给定一个链表以及一个目标值,把小于该目标值的所有节点都移至链表的前端,大于或等于目标值的节点移至链表的尾端,同时要保持这两部分在原先链表中的相对位置。

    public ListNode partition(ListNode head, int x) {
        if(head == null || head.next == null){return head;}
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode smallDummy = new ListNode(0);;
        ListNode largeDummy = new ListNode(0);;
        ListNode smallCur = smallDummy;
        ListNode largeCur = largeDummy;
        while(dummy.next!=null){
            ListNode p = dummy.next;
            if(p.val >= x){
                largeCur.next = p;
                largeCur = largeCur.next;
            }else{
                smallCur.next = p;
                smallCur = smallCur.next;
            }
            dummy = dummy.next;
        }
        smallCur.next = largeDummy.next;
        largeCur.next = null;
        return smallDummy.next;
    }

#328 Odd Even Linked List

奇数位置组合在一起,偶数位置的组合在一起。O(1)空间复杂度,O(n)时间复杂度

public ListNode oddEvenList(ListNode head) {
        if(head == null || head.next == null){return head;}
        ListNode odd = head;
        ListNode even = head.next;
        while(even != null && even.next != null){
            ListNode tmp = even.next;
            even.next = tmp.next;
            tmp.next = odd.next;
            odd.next = tmp;
            odd = tmp;
            even = even.next;
        }
        return head;
    }

#725 Split Linked List in Parts
    public ListNode[] splitListToParts(ListNode root, int k) {
        ListNode p = root;
        int count = 0;
        while(p != null){
            p = p.next;
            count++;
        }
        int team = count / k; //3
        int left = count % k; //1
        ListNode[] res = new ListNode[k];
        for(int i = 0; i < k; i++){
            res[i] = root;
            for(int j = 0; j < team-1 && root!=null; j++){
                root = root.next;
            }
            if(left > 0 && root != null && team > 0){
                root = root.next;
                left--;
            }
            if(root != null){
                ListNode recode = root.next;
                root.next = null;
                root = recode;
            }
        }
        return res;
    }

#2 Add Two Numbers

给定两个链表分别代表两个非负整数。数位以倒序存储,并且每一个节点包含一位数字。将两个数字相加并以链表形式返回

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        int carry = 0;
        ListNode res = new ListNode(0);
        ListNode tmp = res;
        while(l1!=null&&l2!=null){

            int sum = l1.val+l2.val;
            int node = carry + sum;
            carry = 0;
            if(node>9){
                carry++;
            }
            res.next = new ListNode(node%10);
            res = res.next;
            l1 = l1.next;
            l2 = l2.next;
        }
        while (l1 != null) {
            int sum = carry + l1.val;
            res.next = new ListNode(sum % 10);
            carry = sum / 10;
            l1 = l1.next;
            res = res.next;
        }

        while (l2 != null) {
            int sum = carry + l2.val;
            res.next = new ListNode(sum % 10);
            carry = sum / 10;
            l2 = l2.next;
            res = res.next;
        }

        if (carry != 0) {
            res.next = new ListNode(carry);
        }

        return tmp.next;
        // int sum = getNum(l1) + getNum(l2);
        // return getList(sum);
    }
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if(l1 == null || l2 == null){return l1 == null? l2 : l1;}
        int value = l1.val + l2.val;
        ListNode res = new ListNode(value%10);
        res.next = addTwoNumbers(l1.next, l2.next);
        if(value >= 10){
            res.next = addTwoNumbers(new ListNode(value/10), res.next);
        }
        return res;

#445 Add Two Numbers II
       public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        Stack<Integer> s1 = new Stack<>();
        Stack<Integer> s2 = new Stack<>();
        while(l1 != null){
            s1.add(l1.val);
            l1 = l1.next;
        }
        while(l2 != null){
            s2.add(l2.val);
            l2 = l2.next;
        }
        int carry = 0;
        ListNode res = new ListNode(0);
        while(!s1.isEmpty() || !s2.isEmpty()){
            int value = carry;
            if(!s1.isEmpty()) value += s1.pop();
            if(!s2.isEmpty()) value += s2.pop();
            // int value = s1.pop() + s2.pop() + carry;
            ListNode tmp = new ListNode(value % 10);
            tmp.next = res.next;
            res.next = tmp;
            carry = value / 10;
        }
        if(carry != 0){
            ListNode tmp = new ListNode(carry);
            tmp.next = res.next;
            res.next = tmp;
        }
        return res.next;
    }

#19 Remove Nth Node From End of List

删除链表中倒数第n个节点

    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode res = new ListNode(0);
        res.next = head;
        ListNode slow = res;
        ListNode fast = res;
        if(head == null) {
            return null;
        }
        if(head.next == null && n==1){
            return null;
        }
        while(n != 0){
            n--;
            fast = fast.next;
        }
        while(fast.next!=null){
            slow = slow.next;
            fast = fast.next;
        }
        slow.next = slow.next.next;
        return res.next;
    }

#203 Remove Linked List Elements

删除链表中制定元素

    public ListNode removeElements(ListNode head, int val) {
        ListNode res = new ListNode(0);
        res.next = head;
        ListNode cur = res;
        while(cur.next != null){
            if(cur.next.val == val){
                cur.next = cur.next.next;
            }else{
                cur = cur.next;
            }
        }
        return res.next;
    }

#237 Delete Node in a Linked List

just for fun吧~~

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

#83 Remove Duplicates from Sorted List

删除一个有序链表中重复的元素,使得每个元素只出现一次。

 public ListNode deleteDuplicates(ListNode head) {
        if(head == null || head.next == null){return head;}
        ListNode p = head;
        while(p.next != null){
            if(p.val == p.next.val){
                p.next = p.next.next;
            }else{
                p = p.next;
            }
        }
        return head;
    }

#82 Remove Duplicates from Sorted List II

把一个有序链表中所有重复的数字全部删光,删除后不再有原先重复的那些数字。

public ListNode deleteDuplicates(ListNode head) {
        ListNode res = new ListNode(0);
        res.next = head;
        ListNode cur = res;
        ListNode fast = res.next;
        while(cur.next != null){
            while(fast.next!=null && fast.next.val == cur.next.val){
                fast = fast.next;
            }
            if(cur.next == fast){ //没有重复,两个都进一位
                cur = cur.next;
                fast = fast.next;
            }else{
                cur.next = fast.next;
                fast = fast.next;
            }
        }
        return res.next;
    }

#148 Sort List

Sort a linked list in O(n log n) time using constant space complexity.
由于链表在归并操作时并不需要像数组的归并操作那样分配一个临时数组空间,所以这样就是常数空间复杂度了

    public 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){
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode head1 = head;
        ListNode head2 = slow.next;
        slow.next = null;
        head1 = sortList(head1);
        head2 = sortList(head2);
        head = merge(head1,head2);
        return head;
    }
    private ListNode merge(ListNode a, ListNode b){
        ListNode dummy = new ListNode(0);
        ListNode p = dummy;
        while(a!=null && b != null){
            if(a.val <= b.val){
                p.next = a;
                a = a.next;
            }else{
                p.next = b;
                b = b.next;
            }
            p = p.next;
        }
        if(a==null){
            p.next = b;
        }
        if(b == null){
            p.next = a;
        }
        return dummy.next;
    }

#147 Insertion Sort List
    public ListNode insertionSortList(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode p = head.next;
        ListNode q = head;
        while(p!=null){
            if(p.val >= q.val){
                q = p;
                p = p.next;
            }else{
                ListNode p_next = p.next;
                ListNode tmp = dummy.next;
                ListNode pre_tmp = dummy;
                while(tmp.val < p.val && tmp != q){
                    tmp = tmp.next;
                    pre_tmp = pre_tmp.next;
                }
                pre_tmp.next = p;
                p.next = tmp;
                q.next = p_next;
                p = p_next;
            }
        }
        return dummy.next;
    }

#143 Reorder List

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

public void reorderList(ListNode head) {
        if(head == null || head.next == null){
            return;
        }
        ListNode slow = head;
        ListNode fast = head;
        while(fast.next!=null && fast.next.next!=null){
            fast = fast.next.next;
            slow = slow.next;
        }
        fast = slow.next;
        slow.next = null;
        //reverse
        ListNode cur = null;
        while(fast!=null){
            ListNode next = fast.next;
            fast.next = cur;
            cur = fast;
            fast = next;
        }

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

#21 Merge 2 Sorted Lists

修改链表的指针

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null) return l2;
        if(l2 == null) return l1;
        ListNode head = new ListNode(0);
        ListNode p = head;
        while(l1 != null && l2 != null){
            if(l1.val > l2.val){
                p.next = l2;
                p = l2;
                l2 = l2.next;
            }else{
                p.next = l1;
                p = l1;
                l1 = l1.next;
            }
        }
        if(l1 == null){
            p.next = l2;
        }else{
            p.next = l1;
        }
        return head.next;
    }

#23 Merge k Sorted Lists

将k个排序好的链表合并成新的有序链表

public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length==0){return null;}
        PriorityQueue<Integer> q = new PriorityQueue();
        for(ListNode n: lists){
            while(n!=null){
                q.add(n.val);
                n = n.next;
            }
        }
        ListNode dummy = new ListNode(0);
        ListNode p = dummy;
        while(!q.isEmpty()){
            p.next = new ListNode(q.poll());
            p = p.next;
        }
        return dummy.next;
    }

#160 Intersection of Two Linked Lists
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {        
        int l1 = getLength(headA);
        int l2 = getLength(headB);
        while(l1 < l2){
            headB = headB.next;
            l2--;
        }
        while(l1 > l2){
            headA = headA.next;
            l1--;
        }
        while(headA != headB){
            headA = headA.next;
            headB = headB.next;
        }
        return headA == headB? headA: null;
    }
    public int getLength(ListNode a){
        int count = 0;
        while(a != null){
            count++;
            a = a.next;
        }
        return count;
    }
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
         Set<ListNode> s = new HashSet<>();
         while(headA!=null){
             s.add(headA);
             headA = headA.next;
         }
         while(headB!=null){
             if(s.contains(headB)){
                 return headB;
             }else{
                 headB = headB.next;
             }
         }
        return null;
}
         ListNode a = headA;
         ListNode b = headB;
         while(a != b){
             a = a == null ? headA : a.next;
             b = b == null ? headB : b.next;
         }
         return a;
sol1,sol3,sol2
#141 Linked List Cycle

判断一个链表中是否存在着一个环,能否在不申请额外空间的前提下完成

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

#142 Linked List Cycle II

如果给定的单向链表中存在环,则返回环起始的位置,否则返回为空。最好不要申请额外的空间。

    public ListNode detectCycle(ListNode head) {
        ListNode slow = head, fast = head;
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
            if(slow == fast){break;}
        }
        if(fast == null || fast.next == null){return null;}
        slow = head;
        while(slow != fast){
            slow = slow.next;
            fast = fast.next;
        }
        return fast;
    }

#234 Palindrome Linked List
    public boolean isPalindrome(ListNode head) {
        if(head == null || head.next == null){return true;}
        ListNode copyReverse = reverse(head);
        while(head != null){
            if(head.val != copyReverse.val){return false;}
            head = head.next;
            copyReverse = copyReverse.next;
        }
        return true;
    }
    public ListNode reverse(ListNode head){
        ListNode prev = new ListNode(head.val);
        ListNode cur = head;
        while(cur.next!=null){
            ListNode next = new ListNode(cur.next.val); 
            next.next = prev;
            prev = next;
            cur = cur.next;
        }
        return prev;
    }
public boolean isPalindrome(ListNode head) {
        if(head == null || head.next == null){return true;}
        ListNode slow = head, fast = head;
        while(fast.next != null && fast.next.next!=null){
            slow = slow.next;
            fast = fast.next.next;
        }
        fast = slow.next;
        slow.next = null;
        ListNode pre = null;
        ListNode cur = fast;
        while(cur != null){
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        slow = head;
        while(pre != null){
            if(slow.val != pre.val){return false;}
            slow = slow.next;
            pre =pre.next;
        }
        return true;
}

总结

  1. 链表头会发生变化,引入dummy头指针辅助
  2. 交换链表指针时,注意指针变换
  3. 快慢指针用于找中间节点,发现环路等
上一篇下一篇

猜你喜欢

热点阅读