【LeetCode題解】陣列Array
1. 陣列
直觀地看,陣列(Array)為一個二元組<index, value>
的集合——對於每一個index,都有一個value與之對應。C語言中,以“連續的儲存單元”實現陣列:
int arr[5], *p_arr[5];
陣列提供以\(O(1)\)的複雜度訪問元素,下標從0開始。但是,陣列的插入、刪除操作卻非常耗時,因為這涉及到了元素間的移動。
常見的矩陣,可用二維陣列表示。二維陣列本質上是一個一維陣列,其中每個行單元也是一個一維陣列,比如,二維陣列int x[3][5]
的儲存結構如下:
從上圖可以看出,x共有4塊儲存區,一塊用於用以存放行單元指標(x[0:2]),另外三塊用於存放每一個行單元對應的一維陣列。因此,x是一個長度為3的一維陣列,而行單元x[0]又是一個長度為5的一維陣列。
2. 題解
LeetCode題目 | 歸類 |
---|---|
26. Remove Duplicates from Sorted Array | 刪除 |
80. Remove Duplicates from Sorted Array II | 刪除 |
27. Remove Element | 刪除 |
88. Merge Sorted Array | 合併 |
268. Missing Number | 查詢 |
41. First Missing Positive | 查詢 |
287. Find the Duplicate Number | 查詢 |
189. Rotate Array | 旋轉 |
54. Spiral Matrix | 矩陣遍歷 |
59. Spiral Matrix II | |
48. Rotate Image | 矩陣旋轉 |
73. Set Matrix Zeroes |
26. Remove Duplicates from Sorted Array
移除陣列中重複的元素,由於資料是有序的,所以重複元素一定是相鄰的。用兩個pointers,一個用於新陣列生成,一個用於遍歷原陣列:
public int removeDuplicates(int[] nums) { if (nums.length == 0) return 0; int i = 1; for (int j = 1; j < nums.length; j++) { if (nums[j] != nums[i - 1]) nums[i++] = nums[j]; } return i; }
80. Remove Duplicates from Sorted Array II
上一問題的變種,新陣列中最多允許兩個重複元素。
public int removeDuplicates(int[] nums) {
if (nums.length == 0) return 0;
int i = 2;
for (int j = 2; j < nums.length; j++) {
if (nums[j] != nums[i - 2])
nums[i++] = nums[j];
}
return i;
}
27. Remove Element
移去陣列中出現的指定元素。也是用兩個pointers遍歷陣列,從頭尾兩端往中間移動交換:
public int removeElement(int[] nums, int val) {
int i = 0, j = nums.length - 1;
while (i <= j) {
while (j >= i && nums[j] == val) j--; // reduce array size
if (i <= j && nums[i] == val) {
nums[i] = nums[j]; // swap between the current and the last
j--; // reduce array size
}
i++;
}
return j + 1;
}
88. Merge Sorted Array
合併兩個有序陣列,從後往前開始合併:
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m - 1, j = n - 1, k = m + n - 1;
while (j >= 0) {
if (i >= 0 && nums1[i] > nums2[j])
nums1[k--] = nums1[i--];
else
nums1[k--] = nums2[j--];
}
}
268. Missing Number
數的範圍[0,n],找出缺失的數。思路:目標和n*(n+1)/2減去陣列之和即為缺失數。
public int missingNumber(int[] nums) {
int sum = 0, n = nums.length;
for (int i : nums) {
sum += i;
}
return n * (n + 1) / 2 - sum;
}
41. First Missing Positive
找出缺失的第一個正數,陣列的正數範圍在[1,n]。將正數i放在i-1位置上,然後找出缺失數。
public int firstMissingPositive(int[] nums) {
for (int i = 0; i < nums.length; i++) {
while (nums[i] > 0 && nums[i] <= nums.length && nums[i] != nums[nums[i] - 1])
swap(nums, i, nums[i] - 1);
}
for (int i = 0; i < nums.length; i++) {
if (nums[i] != i + 1)
return i + 1;
}
return nums.length + 1;
}
private void swap(int[] A, int a, int b) {
int temp = A[a];
A[a] = A[b];
A[b] = temp;
}
287. Find the Duplicate Number
從陣列中找出重複數,且陣列中的數的範圍在[1,n],且只有一個數重複,重複次數>=2。解決思路:將陣列看作一個移動連結串列,按照index=a[index]方式進行移動;那麼重複元素會使之成為一個有環的連結串列,並且重複的元素為環的開始。故可用快慢兩個指標來解決。
public int findDuplicate(int[] nums) {
int slow = nums[0], fast = nums[nums[0]];
while (slow != fast) { // find the entry point where slow and fast meet
slow = nums[slow];
fast = nums[nums[fast]];
}
for (fast = 0; slow != fast; ) { // find the entry point where the cycle begins
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
189. Rotate Array
指定一個數組截斷點,將左子陣列拼接到右子陣列後。解決思路:現將整個陣列逆序,再將逆序後的左部分逆序、右部分逆序。
public void rotate(int[] nums, int k) {
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
}
// reverse array from begin to end
private void reverse(int[] a, int begin, int end) {
for (int temp; begin < end; begin++, end--) {
temp = a[begin];
a[begin] = a[end];
a[end] = temp;
}
}
54. Spiral Matrix
二維陣列螺旋形遍歷。
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new LinkedList<>();
if (matrix.length == 0) return result;
int m = matrix.length, n = matrix[0].length;
for (int start = 0; m - 1 >= 2 * start && n - 1 >= 2 * start; start++) {
int rowEnd = m - start - 1, colEnd = n - start - 1, i, j;
for (j = start; j <= colEnd; j++) // left move
result.add(matrix[start][j]);
if (rowEnd == start) break;
for (i = start + 1; i <= rowEnd; i++) // down move
result.add(matrix[i][colEnd]);
if (colEnd == start) break;
for (j = colEnd - 1; j >= start; j--) // right move
result.add(matrix[rowEnd][j]);
for (i = rowEnd - 1; i > start; i--) // top move
result.add(matrix[i][start]);
}
return result;
}
59. Spiral Matrix II
上一問題的變種,生成螺旋形二維陣列。
public int[][] generateMatrix(int n) {
int[][] matrix = new int[n][n];
for (int start = 0, cnt = 1; n - 1 >= 2 * start; start++) {
int end = n - start - 1, i, j;
for (j = start; j <= end; j++, cnt++) // left move
matrix[start][j] = cnt;
if (end == start) break;
for (i = start + 1; i <= end; i++, cnt++) // down move
matrix[i][end] = cnt;
for (j = end - 1; j >= start; j--, cnt++) // right move
matrix[end][j] = cnt;
for (i = end - 1; i > start; i--, cnt++) // top move
matrix[i][start] = cnt;
}
return matrix;
}
48. Rotate Image
順時針旋轉矩陣,相當於每一次把四個對應元素做旋轉。
public void rotate(int[][] matrix) {
int n = matrix.length;
for (int i = 0; i < n / 2; i++) {
for (int j = i; j < n - i - 1; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[n - j - 1][i];
matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
matrix[j][n - i - 1] = temp;
}
}
}
73. Set Matrix Zeroes
將有0元素的行與列全置為0;用兩個set儲存這樣的行列,然後再置為0——空間複雜度大概為\(O(m+n)\),並非為最優解。
public void setZeroes(int[][] matrix) {
if (matrix.length == 0) return;
int m = matrix.length, n = matrix[0].length;
Set<Integer> rows = new HashSet<>(); // mark rows which contain 0
Set<Integer> columns = new HashSet<>(); // mark columns which contain 0
// phase 1: find zeroes
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == 0) {
rows.add(i);
columns.add(j);
}
}
}
// phase 2: set rows and columns
for (Integer i : rows) {
for (int j = 0; j < n; j++) {
matrix[i][j] = 0;
}
}
for (Integer j : columns) {
for (int i = 0; i < m; i++) {
matrix[i][j] = 0;
}
}
}
相關推薦
【LeetCode題解】陣列Array
1. 陣列 直觀地看,陣列(Array)為一個二元組<index, value>的集合——對於每一個index,都有一個value與之對應。C語言中,以“連續的儲存單元”實現陣列: int arr[5], *p_arr[5]; 陣列提供以\(O(1)\)的複雜度訪問元素,下標從0開始。但是,陣列的
【LeetCode題解】350_兩個陣列的交集Ⅱ
【LeetCode題解】350_兩個陣列的交集Ⅱ 文章目錄 【LeetCode題解】350_兩個陣列的交集Ⅱ 描述 方法一:對映 Java 實現 Python 實現 類似的 Python 實現
【LeetCode題解】349_兩個陣列的交集
【LeetCode題解】349_兩個陣列的交集 文章目錄 【LeetCode題解】349_兩個陣列的交集 描述 方法一:兩個雜湊表 Java 實現 類似的 Java 實現 Python 實現
【LeetCode題解】160_相交鏈表
結果 user 實現 ini tno href 假設 分享圖片 pytho 目錄 160_相交鏈表 描述 解法一:哈希表 思路 Java 實現 Python 實現 解法二:雙指針(推薦) 思路 Java 實現 Python 實現 160_相交鏈表 描述 編寫一個程
【LeetCode題解】142_環形連結串列2(Linked-List-Cycle-II)
目錄 描述 解法一:雜湊表 思路 Java 實現 Python 實現 複雜度分析 解法二:雙指標 思路 Java 實現 Python 實現 複雜度分析 描述 給定一個連結串列,返回連結串列開始入
【LeetCode題解】61_旋轉連結串列(Rotate-List)
目錄 描述 解法:雙指標 思路 Java 實現 Python 實現 複雜度分析 描述 給定一個連結串列,旋轉連結串列,將連結串列每個節點向右移動 k 個位置,其中 k 是非負數。 示例 1: 輸入: 1->2->3->4-
【LeetCode題解】61_旋轉鏈表(Rotate-List)
__init__ span leetcode 我們 分享 圖片 表示 執行 elf 目錄 描述 解法:雙指針 思路 Java 實現 Python 實現 復雜度分析 描述 給定一個鏈表,旋轉鏈表,將鏈表每個節點向右移動 k 個位置,其中 k 是非負數。 示例 1: 輸入
【LeetCode題解】347_前K個高頻元素(Top-K-Frequent-Elements)
目錄 描述 解法一:排序演算法(不滿足時間複雜度要求) Java 實現 Python 實現 複雜度分析 解法二:最小堆 思路 Java 實現 Python 實現 複雜度分析 解法三:桶排序(bucket s
【LeetCode題解】動態規劃:從新手到專家(一)
【LeetCode題解】動態規劃:從新手到專家(一) 文章標題借用了Hawstein的譯文《動態規劃:從新手到專家》。 1. 概述 動態規劃( Dynamic Programming, DP)是最優化問題的一種解決方法,本質上狀態空間的狀態轉移。所謂狀態轉移是指每個階段的最優狀態(對應於
【LeetCode題解】二叉樹的遍歷
【LeetCode題解】二叉樹的遍歷 我準備開始一個新系列【LeetCode題解】,用來記錄刷題,順便複習一下資料結構與演算法。 1. 二叉樹 二叉樹(binary tree)是一種極為普遍的資料結構,樹的每一個節點最多隻有兩個節點——左孩子結點與右孩子結點。C實現的二叉樹: str
【LeetCode題解】24_兩兩交換連結串列中的節點(Swap-Nodes-in-Pairs)
目錄 描述 解法一:迭代 思路 Java 實現 Python 實現 複雜度分析 解法二:遞迴(不滿足空間複雜度要求) 思路 Java 實現 Python 實現 複雜度分析 更多 LeetCo
【LeetCode題解】19_刪除連結串列的倒數第N個節點(Remove-Nth-Node-From-End-of-List)
更多 LeetCode 題解筆記可以訪問我的 github。 文章目錄 描述 解法:雙指標 思路 Java 實現 Python 實現 複雜度分析 描述 給定一個連結串列,
【LeetCode題解】231_2的冪(Power-of-Two)
文章目錄 描述 解法 1:判斷整數 $x$ 的二進位制表示中是否只有一位為1 實現方式 1:除以 2 Java 實現(非遞迴) Python 實現(非遞迴) Java 實現(遞迴) Python
【LeetCode題解】9_迴文數(Palindrome-Number)
9_迴文數(Palindrome-Number) 文章目錄 9_迴文數(Palindrome-Number) 描述 解法一:轉化為字串的比較 思路 Java 實現 Python 實現 複雜
【LeetCode題解】20_有效的括號(Valid-Parentheses)
20_有效的括號(Valid-Parentheses) 文章目錄 20_有效的括號(Valid-Parentheses) 描述 解法 思路 Java 實現 Python 實現 複雜度分析
【LeetCode題解】206_反轉連結串列(Reverse-Linked-List)
更多 LeetCode 題解筆記可以訪問我的 github。 文章目錄 描述 解法一:迭代 思路 Java 實現 Python 實現 複雜度分析 解法二:遞迴 思路
【LeetCode題解】7_反轉整數
【LeetCode題解】7_反轉整數 文章目錄 【LeetCode題解】7_反轉整數 描述 方法一 思路 Java 實現 類似的 Java 實現 Python 實現 方法
【LeetCode題解】94_二叉樹的中序遍歷
【LeetCode題解】94_二叉樹的中序遍歷 文章目錄 【LeetCode題解】94_二叉樹的中序遍歷 描述 方法一:遞迴 Java 程式碼 Python程式碼 方法二:非遞迴
【LeetCode題解】21_合併兩個有序連結串列
21_合併兩個有序連結串列 文章目錄 21_合併兩個有序連結串列 描述 解法一:迭代 思路 Java 實現 Python 實現 解法二:遞迴 思路 J
【LeetCode題解】237_刪除連結串列中的節點
237_刪除連結串列中的節點 文章目錄 237_刪除連結串列中的節點 描述 解法 思路 Java 實現 Python 實現 描述 請編寫一個函式,使其可以刪除