LeetCode 鏈表專題 2:測試你的鏈表程序

為了測試我們寫的代碼是否正確,我們需要自己寫兩個個方法,這兩個方法對于調試代碼來說是十分有幫助的。

編寫輔助函數(shù):通過一個數(shù)組創(chuàng)建一個鏈表

Java 代碼:

public ListNode createLinkedList(int[] arr) {
    if (arr.length == 0) {
        return null;
    }
    ListNode head = new ListNode(arr[0]);
    ListNode current = head;
    // 把這個迭代想象成一個動畫去理解,就很好理解了
    for (int i = 1; i < arr.length; i++) {
        current.next = new ListNode(arr[i]);
        current = current.next;
    }
    return head;
}

對代碼的說明

1、先創(chuàng)建頭結點,在把頭結點設置為當前節(jié)點,然后開始遍歷,幾乎成為了一個套路;

2、current = current.next; 表示指針后移,模板代碼;

3、用頭結點就可以代表一個鏈表,所以返回的是 head

注意:要考慮到數(shù)組為空的情況。

編寫輔助函數(shù):通過一個鏈表的頭結點打印一個鏈表

Java 代碼:

public void printLinkedList(ListNode head){
    ListNode current =  head;
    while (current!=null){
        System.out.printf("%d -> ",current.val);
        current = current.next;
    }
    System.out.println("NULL");
}

下面我們在 main 函數(shù)中測試一下。

public static void main(String[] args) {
    int[] arr = {1,2,3,4,5};
    Solution solution = new Solution();
    ListNode list1 = solution.createLinkedList(arr);
    solution.printLinkedList(list1);
    ListNode list2 = solution.reverseList(list1);
    solution.printLinkedList(list2);
}

練習

練習1:LeetCode 第 83 題:從一個有序的列表中刪除重復的元素

傳送門:刪除排序鏈表中的重復元素。

給定一個排序鏈表,刪除所有重復的元素,使得每個元素只出現(xiàn)一次。

示例 1:

輸入: 1->1->2
輸出: 1->2

示例 2:

輸入: 1->1->2->3->3
輸出: 1->2->3

思路:有序鏈表,相同元素最多保留 1 個。

Python 代碼:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

# 給定一個排序鏈表,刪除所有重復的元素,使得每個元素只出現(xiàn)一次。
# 【判斷的條件是"下一個結點"】


class Solution(object):
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        # 先判斷極端條件
        if head is None or head.next is None:
            return head
        cur = head
        while cur.next:
            next = cur.next
            if next.val == cur.val:
                # q 向后挪動一位
                cur.next = next.next
                next.next = None
            else:
                cur = cur.next
        return head

練習2:LeetCode 第 86 題:分割鏈表

英文網(wǎng)址:86. Partition List ,中文網(wǎng)址:86. 分隔鏈表

給定一個鏈表和一個特定值 x,對鏈表進行分隔,使得所有小于 x 的節(jié)點都在大于或等于 x 的節(jié)點之前。

你應當保留兩個分區(qū)中每個節(jié)點的初始相對位置。

示例:

輸入: head = 1->4->3->2->5->2, x = 3
輸出: 1->2->2->4->3->5

思路:分別拿兩個虛擬頭結點,最后拼在一起。

Java 代碼:

public class Solution2 {

    // 空間復雜度為常數(shù)的解法:穿針引線

    public ListNode partition(ListNode head, int x) {
        // 比 x 小的虛擬頭結點
        ListNode dummyNodeL = new ListNode(-1);
        // 大于等于 x 的虛擬頭結點
        ListNode dummyNodeR = new ListNode(-1);
        // 用于遍歷
        ListNode curL = dummyNodeL;
        // 用于遍歷
        ListNode curR = dummyNodeR;
        int val;
        while (head != null) {
            val = head.val;
            if (val < x) {
                curL.next = head;
                curL = curL.next;
            } else {
                curR.next = head;
                curR = curR.next;
            }
            head = head.next;
        }
        curL.next = dummyNodeR.next;
        // 特別注意:最后這一步不能忘記,否則會產生一個循環(huán)鏈表
        curR.next = null;
        return dummyNodeL.next;
    }

    public static void main(String[] args) {
        int[] nums = {1, 4, 3, 2, 5, 2};
        int x = 3;
        ListNode head = new ListNode(nums);
        Solution2 solution2 = new Solution2();
        System.out.println("分隔鏈表之后:");
        ListNode partition = solution2.partition(head, x);
        System.out.println(partition);
    }
}

練習3:LeetCode 第 328 題:奇數(shù)(Odd)偶數(shù)(Even)鏈表

傳送門:英文網(wǎng)址:328. Odd Even Linked List ,中文網(wǎng)址:328. 奇偶鏈表

給定一個單鏈表,把所有的奇數(shù)節(jié)點和偶數(shù)節(jié)點分別排在一起。請注意,這里的奇數(shù)節(jié)點和偶數(shù)節(jié)點指的是節(jié)點編號的奇偶性,而不是節(jié)點的值的奇偶性。

請嘗試使用原地算法完成。你的算法的空間復雜度應為 O(1),時間復雜度應為 O(nodes),nodes 為節(jié)點總數(shù)。

示例 1:

輸入: 1->2->3->4->5->NULL
輸出: 1->3->5->2->4->NULL

示例 2:

輸入: 2->1->3->5->6->4->7->NULL 
輸出: 2->3->6->7->1->5->4->NULL

說明:

  • 應當保持奇數(shù)節(jié)點和偶數(shù)節(jié)點的相對順序。
  • 鏈表的第一個節(jié)點視為奇數(shù)節(jié)點,第二個節(jié)點視為偶數(shù)節(jié)點,以此類推。

思路:題目要求原地算法完成,那么就一定得“穿針引線”了。

  • 方法1:可以使用 LeetCode 第 86 題題解思路 2 完成。
  • 方法2:同樣使用兩個指針,一次跳過一個節(jié)點完成“穿針引線”,特別注意要一些邊界情況的判斷。
LeetCode 第 328 題:奇數(shù)(Odd)偶數(shù)(Even)鏈表

Python 代碼:

class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None


class Solution:
    def oddEvenList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """

        if head is None or head.next is None:
            return head

        # odd 奇數(shù)
        odd_head = head
        even_head = head.next

        odd_cur = odd_head
        even_cur = even_head

        while even_cur and even_cur.next:
            odd_cur.next = odd_cur.next.next
            even_cur.next = even_cur.next.next

            odd_cur = odd_cur.next
            even_cur = even_cur.next

        odd_cur.next = even_head
        return odd_head

我還寫過一個題解在這里,可以參考一下。

練習4:LeetCode 第 2 題:兩個數(shù)相加

傳送門:英文網(wǎng)址:2. Add Two Numbers ,中文網(wǎng)址:2. 兩數(shù)相加 。

給出兩個 非空 的鏈表用來表示兩個非負的整數(shù)。其中,它們各自的位數(shù)是按照 逆序 的方式存儲的,并且它們的每個節(jié)點只能存儲 一位 數(shù)字。

如果,我們將這兩個數(shù)相加起來,則會返回一個新的鏈表來表示它們的和。

您可以假設除了數(shù)字 0 之外,這兩個數(shù)都不會以 0 開頭。

示例:

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807

思路:需要考慮的問題:1、數(shù)字中是否有前置的0(除了0以外,沒有前置的0);2、負數(shù)是否考慮。
編碼過程中需要思考的問題:1、如何分別獲得這個數(shù)組的個位、十位、百位、千位;2、分別相加,如果大于 10,進一。

Python 代碼:

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None


class Solution:
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        if l1 is None:
            return l2

        if l2 is None:
            return l1

        dummy_node = ListNode(-1)
        cur_node = dummy_node
        s = 0

        # 只要二者之一非空,就加下去
        while l1 or l2:
            if l1:
                s += l1.val
                l1 = l1.next
            if l2:
                s += l2.val
                l2 = l2.next
            cur_node.next = ListNode(s % 10)
            s //= 10
            cur_node = cur_node.next
        if s == 1:
            cur_node.next = ListNode(1)
        return dummy_node.next

練習5:LeetCode 第 445 題:兩個數(shù)相加

傳送門:英文網(wǎng)址:445. Add Two Numbers II ,中文網(wǎng)址:445. 兩數(shù)相加 II 。

給定兩個非空鏈表來代表兩個非負整數(shù)。數(shù)字最高位位于鏈表開始位置。它們的每個節(jié)點只存儲單個數(shù)字。將這兩數(shù)相加會返回一個新的鏈表。

你可以假設除了數(shù)字 0 之外,這兩個數(shù)字都不會以零開頭。

進階:

如果輸入鏈表不能修改該如何處理?換句話說,你不能對列表中的節(jié)點進行翻轉。

示例:

輸入: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出: 7 -> 8 -> 0 -> 7

思路:需要考慮的問題是如果不允許修改輸入的鏈表該怎么辦;使用一個輔助的數(shù)據(jù)結構來完成。

Python 代碼:

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None


class Solution:
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        stack1 = []
        stack2 = []
        p1 = l1
        p2 = l2
        while p1:
            stack1.append(p1.val)
            p1 = p1.next
        while p2:
            stack2.append(p2.val)
            p2 = p2.next
        res = []
        s = 0
        while stack1 or stack2:
            if stack1:
                s += stack1.pop()
            if stack2:
                s += stack2.pop()
            res.append(s % 10)
            s //= 10
        if s == 1:
            res.append(1)
        head = ListNode(res.pop())
        cur_node = head
        while len(res):
            cur_node.next = ListNode(res.pop())
            cur_node = cur_node.next
        return head

(本節(jié)完)

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容