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

Java研究者發表於2023-10-16

陣列(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來進行思考,字首和就是典型一種示例。

相關文章