LeetCode中的數據結構2:鏈表

鏈表問題要尤其注意,檢查邊界條件是否考慮全面,代碼在邊界條件下是否能正確運行,如:鏈表爲空、鏈表只包含一個結點、鏈表只包含兩個結點、代碼邏輯處理頭結點和尾結點時,能否正常執行。

下面是鏈表問題常用的幾種解題思路。

快慢指針

LeetCode 141. Linked List Cycle
https://leetcode.com/problems/linked-list-cycle/
Given a linked list, determine if it has a cycle in it.判斷鏈表是否有環

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

LeetCode 234. Palindrome Linked List
https://leetcode.com/problems/palindrome-linked-list/
Given a singly linked list, determine if it is a palindrome. 對於一個給定的鏈表,判斷是否爲迴文串。可以分爲4步,

  1. 使用快慢指針找到鏈表中間的節點;
  2. 反轉後半鏈表;
  3. 從頭結點和中間節點開始遍歷比較;
  4. 將後半鏈表恢復。
    這其實可以拆解成兩個常見問題 1)尋找單鏈表的中間節點 2)反轉鏈表。
class Solution {
    public boolean isPalindrome(ListNode head) {
        int length = 0;
        ListNode cur = head;
        while(cur != null) {
            length++;
            cur = cur.next;
        }
        ListNode midNode = head;
        for (int i=1; i<length/2+1; i++) {
            midNode = midNode.next;
        }
        // 從midNode開始反轉鏈表
        ListNode newNode = reverseList(midNode);
        // 從head和newNode開始,判斷前後兩段是否相等
        while (head != null && newNode != null) {
            if(head.val != newNode.val) {
                return false;
            }
            head = head.next;
            newNode = newNode.next;
        }
        return true;
    }
    
    private ListNode reverseList(ListNode node) {
        if (node == null || node.next == null) {
            return node;
        }
        ListNode newHead = reverseList(node.next);
        node.next.next = node;
        node.next = null;
        return newHead;
    }
}

LeetCode 160. Intersection of Two Linked Lists
https://leetcode.com/problems/intersection-of-two-linked-lists/
Write a program to find the node at which the intersection of two singly linked lists begins. 查找兩個鏈表的第一個公共節點。

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }
        ListNode a = headA;
        ListNode b = headB;
        while (a != b) {
            a = a == null ? headB : a.next;
            b = b == null ? headA : b.next;
        }
        return a;        
    }
}

LeetCode 19 Remove Nth Node From End of List
https://leetcode.com/problems/remove-nth-node-from-end-of-list
Given a linked list, remove the n-th node from the end of list and return its head.

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

LeetCode 61 Rotate List
https://leetcode.com/problems/rotate-list
Given a linked list, rotate the list to the right by k places, where k is non-negative.

public ListNode rotateRight(ListNode head, int k) {
    if (head==null) {
        return head;
    }
    ListNode node = head;
    int length = 0;
    while (node != null) {
        node = node.next;
        length++;
    }
    int n = k%length;
    if (n==0) {
        return head;
    }
    
    ListNode fast = head;
    ListNode slow = head;
    ListNode preSlow = null;
    ListNode preFast = null;
    while (n>0) {
        fast = fast.next;
        n--;
    }
    while (fast != null) {
        preFast = fast;
        preSlow = slow;
        fast = fast.next;
        slow = slow.next;
    }
    preSlow.next = null;
    preFast.next = head;
    return slow;
}
虛擬頭節點

LeetCode 203. Remove Linked List Elements
https://leetcode.com/problems/remove-linked-list-elements/
Remove all elements from a linked list of integers that have value val.

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

LeetCode 82. Remove Duplicates from Sorted List II
https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

public ListNode deleteDuplicates(ListNode head) {
    ListNode dummyHead = new ListNode(0);
    dummyHead.next = head;
    ListNode cur = head;
    Map<Integer, Integer> map = new HashMap<>();
    while(cur != null) {
        if (map.containsKey(cur.val)) {
            map.put(cur.val, map.get(cur.val)+1);
        } else {
            map.put(cur.val, 1);
        }
        cur = cur.next;
    }
    cur = dummyHead;
    while (cur != null && cur.next != null) {
        if (map.get(cur.next.val)>1) {
            cur.next = cur.next.next;
        } else {
            cur = cur.next;
        } 
    }
    return dummyHead.next;
}
操作指針

LeetCode 147 Insertion Sort List
https://leetcode.com/problems/insertion-sort-list
Sort a linked list using insertion sort.

public ListNode insertionSortList(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode newListDummyHead = new ListNode(Integer.MIN_VALUE);
    ListNode cur = head;
    while (cur != null) {
        ListNode tempNode = newListDummyHead;
        while (tempNode.next != null && tempNode.next.val < cur.val) {
            tempNode = tempNode.next;
        }
        ListNode tempNext =tempNode.next;
        ListNode curNext = cur.next;
        tempNode.next = cur;
        cur.next = tempNext;
        cur = curNext;
    }
    return newListDummyHead.next;         
}

LeetCode 24. Swap Nodes in Pairs
https://leetcode.com/problems/swap-nodes-in-pairs/
Given a linked list, swap every two adjacent nodes and return its head. You may not modify the values in the list’s nodes, only nodes itself may be changed.

public ListNode swapPairs(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode ret  = head.next;
    ListNode pre = new ListNode(0);
    pre.next = head;
    ListNode node1 = pre.next;
    while(node1!=null && node1.next!=null){
        ListNode node2 = node1.next;
        ListNode next = node2.next;
        node1.next = next;
        node2.next = node1;
        pre.next = node2;
        pre = node1;
        node1 = next;
    }
    return ret;
}

LeetCode 92 Reverse Linked List II
https://leetcode.com/problems/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) {
    ListNode pre = null;
    ListNode cur = head;
    while (m>1) {
        pre = cur;
        cur = cur.next;
        m--;
        n--;
    }
    ListNode con = pre, tail = cur;
    while (n>0) {
        ListNode next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
        n--;
    }
    if (con != null) {
        con.next = pre;
    } else {
        head = pre;
    }
    tail.next = cur;   
    return head;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章