leetcode刷題筆記8.5-8.9

CandyWang-發表於2024-08-12

刷題筆記8.5-8.9

刷題順序依照labuladong演算法小抄

兩數之和(8.5)

  1. 初始化陣列:
    int[] num = new int<length>;
    int[] num = {1,2,3,4};
    其中陣列名代表指標變數,故不可以直接將陣列名a賦值給陣列名b
    錯誤的複製:int[] b = a;
  2. 陣列元素複製:
    假設陣列nums的元素複製到numsSort中:
    int[] numsSort = (int[])Arrays.copyOf(nums,nums.length)
    意為為numsSort指向的儲存區內開闢nums.length長度的空間,並複製nums
  3. 呼叫Arrays靜態類中的方法可以直接運算元組
    1) 陣列預設升序排列:Arrays.sort(nums)
  4. 使用arraylist.indexOf(Object o)來定位指定元素索引
    第一步:一個陣列或者其他集合類建立一個不可變的 List 集合時,我們可以使用 Arrays.asList() 來方便地轉換
String[] array = {"a","b","c","d"}; // 現有靜態陣列或集合
List<String> list = Array.asList(array); // 轉換為長度不可變的Arraylist

或者直接賦值

List<String> list = Arrays.asList("a", "b", "c")

第二步:int index = list.indexOf("b");
【注意】
Arrays.asList() 不支援基本資料型別的陣列,只能接受 Object 型別的引數或者陣列。基本資料型別(如 int, double, char 等)不是 Object 的子類,所以不能直接作為 Arrays.asList() 的引數。
如果傳入一個基本資料型別的陣列,Arrays.asList() 會把它當作一個 Object 型別的元素,而不是把它的每個元素當作 Object 型別。這樣就會導致返回的 List 只有一個元素,就是原始陣列本身。

  • 如果想要把一個基本資料型別的陣列轉換成 List
    使用迴圈遍歷陣列,並把每個元素新增到 List 中。這樣可以利用自動裝箱(autoboxing)的特性,把基本資料型別轉換成對應的包裝類(如 Integer, Double, Character 等)。
List<Integer> list = new ArrayList<>();
int[] array = {1,2,3};
for(int num:array){
  list.add(num);
}

刷題總結(8.6)

  1. 靜態陣列在建立的時候就要確定陣列的元素型別和元素數量,連續記憶體必須一次性分配,分配完了之後就不能隨意增減了
int[] nums = new int[4];

Java Golang 這種語言,靜態陣列建立出來後會自動幫你把元素值都初始化為 0,所以不需要再顯式進行初始化。
2. 動態陣列底層還是靜態陣列,只是自動幫我們進行陣列空間的擴縮容,並把增刪查改操作進行了封裝,讓我們使用起來更方便而已

// 建立動態陣列
// 不用顯式指定陣列大小,它會根據實際儲存的元素數量自動擴縮容
ArrayList<Integer> arr = new ArrayList<>();

for (int i = 0; i < 10; i++) {
    // 在末尾追加元素,時間複雜度 O(1)
    arr.add(i);
}

// 在中間插入元素,時間複雜度 O(N)
// 在索引 2 的位置插入元素 666
arr.add(2, 666);

// 在頭部插入元素,時間複雜度 O(N)
arr.add(0, -1);

// 刪除末尾元素,時間複雜度 O(1)
arr.remove(arr.size() - 1);

// 刪除中間元素,時間複雜度 O(N)
// 刪除索引 2 的元素
arr.remove(2);

// 根據索引查詢元素,時間複雜度 O(1)
int a = arr.get(0);

// 根據索引修改元素,時間複雜度 O(1)
arr.set(0, 100);

// 根據元素值查詢索引,時間複雜度 O(N)
int index = arr.indexOf(666);
  1. 廣義的(雙指標)連結串列
    資料結構體定義
private static class Node<E> {
    E val; // 結點儲存的數值
    Node<E> next; // 當前結點指向的下一個
    Node<E> prev; // 當前結點指向的上一個

    Node(Node<E> prev, E element, Node<E> next) {
        this.val = element;
        this.next = next;
        this.prev = prev;
    }
}

一條連結串列並不需要一整塊連續的記憶體空間儲存元素。連結串列的元素可以分散在記憶體空間的天涯海角,透過每個節點上的 next, prev 指標,將零散的記憶體塊串聯起來形成一個鏈式結構。

刷題總結(8.8)

  1. 關於優先順序佇列:
    使用場景:對k個元素排序,將陣列/序列抽象為二叉堆
    使用方法:
  • 優先順序佇列初始化:
// 堆排序偽碼,對 arr 原地排序
// 時間複雜度 O(NlogN),空間複雜度 O(N)
int[] heapSort(int[] arr) {
    int[] res = new int[arr.length];
    PriorityQueue<int> pq = new MyPriorityQueue<>();
    for (int x : arr)
        pq.push(x);
    // 元素出堆的順序是有序的
    for (int i = 0; i < arr.length; i++)
        res[i] = pq.pop();
    return res;
}
  • 優先順序佇列按特定規則比較排序
PriorityQueue<ListNode> pq = new PriorityQueue<>(
            lists.length, (a, b)->(a.val - b.val));

(a, b)->(a.val - b.val)是一個lambda表示式,它定義了優先佇列中元素的排序規則。在Java中,優先佇列預設是一個最小堆,這意味著它將根據提供的比較器來維護元素的順序,使得佇列頭部始終是“最小”的元素。
a.val - b.val是一個比較操作,它比較兩個ListNode物件的val值。根據這個比較結果,優先佇列確定元素的順序,即 如果a.val - b.val的結果小於0,那麼a將被視為比b小,a會排在b前面。
綜上,上面這段程式碼表示:優先佇列儲存著ListNode型別的元素,但佇列是按照ListNode物件的val欄位進行排序,確保具有最小val值的ListNode物件始終位於佇列的頭部。

  • 注意:優先順序佇列中的元素不可為空,否則會報java.lang.NullPointerException,在執行pq.add(x)時跟隨判斷

相關文章