資料結構與演演算法 | 陣列(Array)

2023-10-16 18:00:39

陣列(Array)

陣列(Array)應該是最基礎的資料結構之一,它由相同型別的元素組成的集合,並按照一定的順序儲存在記憶體中。每個元素都有一個唯一的索引,可以用於存取該元素。

	// java 陣列範例
	int[] numbers1 = {2,0,2,3,9,23};
	// 或者
	int[] numbers2 = new int[6];

基本概念

陣列基本概念 —— 陣列索引、陣列元素、陣列長度

  • 陣列索引(Index): 陣列中的每個元素都有一個唯一的整數索引,從0開始計數。索參照於存取陣列中的元素。
  • 陣列元素(Element): 陣列中的元素必須是相同型別的資料,可以是整數、浮點數、字元、物件等。
  • 陣列長度(Length): 陣列的長度是指陣列中包含的元素數量。

其具備一些性質:

  • 連續儲存(Contiguous Memory): 陣列中的元素在記憶體中是連續儲存的,這意味著通過索引可以直接計算出元素的地址。
  • 隨機存取時間(Constant Time Access): 由於元素的連續儲存和索引的存在,通過索引存取陣列中的某個元素通常只需要常數時間O(1)。( PS: 什麼叫隨機存取? 是計算機領域的一個重要概念,指的是能夠以大致相等的時間存取儲存媒介中的任何資料元素,而不受其物理儲存位置順序的限制。通俗點說,隨便獲取任意一個元素。)

基本應用(Basic)

陣列的結構本身比較簡單,在解決常見面試演演算法問題中靈活應用陣列索引來存取資料是關鍵。

Leetcode 26. 刪除有序陣列中的重複項【簡單】

給你一個 非嚴格遞增排列 的陣列 nums ,請你 原地 刪除重複出現的元素,使每個元素 只出現一次 ,返回刪除後陣列的新長度。元素的 相對順序 應該保持 一致 。然後返回 nums 中唯一元素的個數。

LeetCode 674. 最長連續遞增序列【簡單】

給定一個未經排序的整數陣列,找到最長且 連續遞增的子序列,並返回該序列的長度。

連續遞增的子序列 可以由兩個下標 l 和 r(l < r)確定,如果對於每個 l <= i < r,都有 nums[i] < nums[i + 1] ,那麼子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是連續遞增子序列。

雙指標(Two Pointers)

一些資料上也有說雙指標演演算法,筆者看來更傾向於是一種技巧,定義的兩個索引指標 通過操作兩個索引指標來獲取問題答案。(PS:為什麼這裡叫指標?指標更多的是C語言中的概念,最早C語言解決演演算法問題比較多。)

根據指標移動 或者 所指位置不同,也有不少其他種分類的說法比如:對撞指標、快慢指標、分離指標等等;但其技巧本質都是在於操作兩個指標索引,大可不必嚴格定義這些名稱,需要的是抓住重點操作兩個指標。

LeetCode 167. 兩數之和 II - 輸入有序陣列【中等】

給你一個下標從 1 開始的整數陣列 numbers ,該陣列已按 非遞減順序排列 ,請你從陣列中找出滿足相加之和等於目標數 target 的兩個數。如果設這兩個數分別是 numbers[index1] 和 numbers[index2] ,則 1 <= index1 < index2 <= numbers.length 。

以長度為 2 的整數陣列 [index1, index2] 的形式返回這兩個整數的下標 index1 和 index2。
你可以假設每個輸入 只對應唯一的答案 ,而且你 不可以 重複使用相同的元素。

LeetCode 15. 三數之和【中等】

給你一個整數陣列 nums ,判斷是否存在三元組 [nums[i], nums[j], nums[k]] 滿足 i != j、i != k 且 j != k ,同時還滿足 nums[i] + nums[j] + nums[k] == 0 。請你返回所有和為 0 且不重複的三元組。

注意:答案中不可以包含重複的三元組。

字首和(Prefix Sum)

對於一些演演算法問題直接求解的思路可能計算量比較大,可以思考利用預處理一組特定的中間資料來進求解。類比就如同初中解一些幾何題通過幾條輔助線的解法,如果回顧學習輔助線的畫法,往往先了解常見的畫法;對於演演算法,字首和就是「常見的輔助線畫法」。

針對一些演演算法問題需要快速計算陣列某個連續區間的數值和時,先計算字首和陣列會是一個很好的策略。相關推導如下:

LeetCode 1343. 大小為 K 且平均值大於等於閾值的子陣列數目【中等】

給你一個整數陣列 arr 和兩個整數 k 和 threshold 。
請你返回長度為 k 且平均值大於等於 threshold 的子陣列數目。

範例 1:
輸入:arr = [2,2,2,2,5,5,5,8], k = 3, threshold = 4
輸出:3
解釋:子陣列 [2,5,5],[5,5,5] 和 [5,5,8] 的平均值分別為 4,5 和 6 。其他長度為 3 的子陣列的平均值都小於 4 (threshold 的值)。

總結下

  • 介紹了陣列的基本結構,三個基本概念: 陣列索引、陣列元素、陣列長度;
  • 陣列類基礎題,關鍵在於靈活的三個基本概念;
  • 利用操作兩個陣列索引的程式設計技巧來解決問題(雙指標);
  • 解決演演算法問題,求解C,可以先 A->B->C來進行思考,字首和就是典型一種範例。