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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章