LeetCode 陣列
基礎部分
283. 移動零
簡單
給定一個數組 nums
,編寫一個函式將所有 0
移動到陣列的末尾,同時保持非零元素的相對順序。
示例:
輸入: [0,1,0,3,12]
輸出: [1,3,12,0,0]
說明:
- 必須在原陣列上操作,不能拷貝額外的陣列。
- 儘量減少操作次數。
class Solution { public void moveZeroes(int[] nums) { if (nums == null || nums.length < 2) return; int i = 0, len = nums.length, j, tmp; while (i < len){ while (i < len && nums[i] != 0) i++; j = i + 1; while (j < len && nums[j] == 0) j++; if (j >= len) break; tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } } }
566. 重塑矩陣
簡單
在MATLAB中,有一個非常有用的函式 reshape
,它可以將一個矩陣重塑為另一個大小不同的新矩陣,但保留其原始資料。
給出一個由二維陣列表示的矩陣,以及兩個正整數r
和c
,分別表示想要的重構的矩陣的行數和列數。
重構後的矩陣需要將原始矩陣的所有元素以相同的行遍歷順序填充。
如果具有給定引數的reshape
操作是可行且合理的,則輸出新的重塑矩陣;否則,輸出原始矩陣。
示例 1:
輸入: nums = [[1,2], [3,4]] r = 1, c = 4 輸出: [[1,2,3,4]] 解釋: 行遍歷nums的結果是 [1,2,3,4]。新的矩陣是 1 * 4 矩陣, 用之前的元素值一行一行填充新矩陣。
示例 2:
輸入:
nums =
[[1,2],
[3,4]]
r = 2, c = 4
輸出:
[[1,2],
[3,4]]
解釋:
沒有辦法將 2 * 2 矩陣轉化為 2 * 4 矩陣。 所以輸出原矩陣。
注意:
- 給定矩陣的寬和高範圍在 [1, 100]。
- 給定的 r 和 c 都是正數。
class Solution { public int[][] matrixReshape(int[][] nums, int r, int c) { int m = nums.length; int n = nums[0].length; if (m * n != r * c) return nums; int[][] res= new int[r][c]; for (int i = 0; i < r; i++){ for (int j = 0; j < c; j++){ int index = i * c + j; res[i][j] = nums[index/n][index%n]; } } return res; } }
485. 最大連續1的個數
簡單
給定一個二進位制陣列, 計算其中最大連續1的個數。
示例 1:
輸入: [1,1,0,1,1,1]
輸出: 3
解釋: 開頭的兩位和最後的三位都是連續1,所以最大連續1的個數是 3.
注意:
- 輸入的陣列只包含
0
和1
。 - 輸入陣列的長度是正整數,且不超過 10,000。
class Solution {
public int findMaxConsecutiveOnes(int[] nums) {
int res = nums[0];
for (int i = 1; i < nums.length; i++){
if (nums[i] == 1) {
nums[i] = nums[i-1] + 1;
if (nums[i] > res) res = nums[i];
}
}
return res;
}
}
240. 搜尋二維矩陣 II
中等
編寫一個高效的演算法來搜尋 m x n 矩陣 matrix 中的一個目標值 target。該矩陣具有以下特性:
- 每行的元素從左到右升序排列。
- 每列的元素從上到下升序排列。
示例:
現有矩陣 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
給定 target = 5
,返回 true
。
給定 target = 20
,返回 false
。
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix.length == 0 || matrix[0].length == 0) return false;
int row = matrix.length;
int i = 0, j = matrix[0].length - 1;
while (i < row && j >= 0){
if (matrix[i][j] == target) return true;
else if (matrix[i][j] > target) j--;
else i++;
}
return false;
}
}
378. 有序矩陣中第K小的元素
中等
給定一個 n x n
矩陣,其中每行和每列元素均按升序排序,找到矩陣中第 k
小的元素。
請注意,它是排序後的第 k
小元素,而不是第 k
個不同的元素。
示例:
matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,
返回 13。
提示:
你可以假設 k 的值永遠是有效的,1 ≤ k ≤ n^2
。
class Solution {
public int kthSmallest(int[][] matrix, int k) {
int n = matrix.length;
int[] res = new int[n*n];
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
res[i*n+j] = matrix[i][j];
}
}
Arrays.sort(res);
return res[k-1];
}
}
645. 錯誤的集合
簡單
集合 S
包含從1到 n
的整數。不幸的是,因為資料錯誤,導致集合裡面某一個元素複製了成了集合裡面的另外一個元素的值,導致集合丟失了一個整數並且有一個元素重複。
給定一個數組 nums
代表了集合 S
發生錯誤後的結果。你的任務是首先尋找到重複出現的整數,再找到丟失的整數,將它們以陣列的形式返回。
示例 1:
輸入: nums = [1,2,2,4]
輸出: [2,3]
注意:
- 給定陣列的長度範圍是 [2, 10000]。
- 給定的陣列是無序的。
class Solution {
public int[] findErrorNums(int[] nums) {
int[] map = new int[nums.length+1];
for (int num : nums) map[num]++;
int[] res = new int[2];
for (int i = 1; i < map.length; i++){
if (map[i] == 1) continue;
else if (map[i] == 2) res[0] = i;
else res[1] = i;
}
return res;
}
}
287. 尋找重複數
中等
給定一個包含 n + 1 個整數的陣列 nums,其數字都在 1 到 n 之間(包括 1 和 n),可知至少存在一個重複的整數。假設只有一個重複的整數,找出這個重複的數。
示例 1:
輸入: [1,3,4,2,2]
輸出: 2
示例 2:
輸入: [3,1,3,4,2]
輸出: 3
說明:
- 不能更改原陣列(假設陣列是隻讀的)。
- 只能使用額外的 O(1) 的空間。
- 時間複雜度小於 O(n2) 。
- 陣列中只有一個重複的數字,但它可能不止重複出現一次。
class Solution {
public int findDuplicate(int[] nums) {
int[] map = new int[nums.length];
for (int num : nums){
map[num]++;
if (map[num] == 2) return num;
}
return 0;
}
}
667. 優美的排列 II
中等
給定兩個整數 n
和 k
,你需要實現一個數組,這個陣列包含從 1
到 n
的 n
個不同整數,同時滿足以下條件:
① 如果這個陣列是 [a1, a2, a3, ... , an] ,那麼陣列 [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] 中應該有且僅有 k 個不同整數;.
② 如果存在多種答案,你只需實現並返回其中任意一種.
示例 1:
輸入: n = 3, k = 1
輸出: [1, 2, 3]
解釋: [1, 2, 3] 包含 3 個範圍在 1-3 的不同整數, 並且 [1, 1] 中有且僅有 1 個不同整數 : 1
示例 2:
輸入: n = 3, k = 2
輸出: [1, 3, 2]
解釋: [1, 3, 2] 包含 3 個範圍在 1-3 的不同整數, 並且 [2, 1] 中有且僅有 2 個不同整數: 1 和 2
提示:
n
和k
滿足條件 1 <= k < n <= 10^4.
class Solution {
public int[] constructArray(int n, int k) {
int[] res = new int[n];
for (int i = 0; i < n; i++) res[i] = i + 1;
int i = 1;
while (--k > 0) reverse(res,i++,n-1);
return res;
}
private void reverse(int[] nums,int l,int r){
int tmp;
while (l < r){
tmp = nums[l];
nums[l] = nums[r];
nums[r] = tmp;
l++;
r--;
}
}
}
697. 陣列的度
簡單
給定一個非空且只包含非負數的整數陣列 nums
, 陣列的度的定義是指數組裡任一元素出現頻數的最大值。
你的任務是找到與 nums
擁有相同大小的度的最短連續子陣列,返回其長度。
示例 1:
輸入: [1, 2, 2, 3, 1]
輸出: 2
解釋:
輸入陣列的度是2,因為元素1和2的出現頻數最大,均為2.
連續子數組裡面擁有相同度的有如下所示:
[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
最短連續子陣列[2, 2]的長度為2,所以返回2.
示例 2:
輸入: [1,2,2,3,1,4,2]
輸出: 6
注意:
nums.length
在1到50,000區間範圍內。nums[i]
是一個在0到49,999範圍內的整數。
class Solution {
public int findShortestSubArray(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
for (int num : nums)
map.put(num,map.getOrDefault(num,0)+1);
List<Integer> maxs = new ArrayList<>();
int maxcount = 0;
for (Integer key : map.keySet()){
maxcount = Math.max(maxcount,map.get(key));
}
if (maxcount < 2) return maxcount;
for (Integer key : map.keySet()){
if (map.get(key) == maxcount) maxs.add(key);
}
int res = nums.length;
for (Integer max : maxs){
int i = 0, j = nums.length-1;
while (nums[i] != max) i++;
while (nums[j] != max) j--;
res = Math.min(res,j-i+1);
}
return res;
}
}
766. 託普利茨矩陣
簡單
如果矩陣上每一條由左上到右下的對角線上的元素都相同,那麼這個矩陣是 託普利茨矩陣 。
給定一個 M x N
的矩陣,當且僅當它是託普利茨矩陣時返回 True
。
示例 1:
輸入:
matrix = [
[1,2,3,4],
[5,1,2,3],
[9,5,1,2]
]
輸出: True
解釋:
在上述矩陣中, 其對角線為:
"[9]", "[5, 5]", "[1, 1, 1]", "[2, 2, 2]", "[3, 3]", "[4]"。
各條對角線上的所有元素均相同, 因此答案是True。
示例 2:
輸入:
matrix = [
[1,2],
[2,2]
]
輸出: False
解釋:
對角線"[1, 2]"上的元素不同。
說明:
matrix
是一個包含整數的二維陣列。matrix
的行數和列數均在[1, 20]
範圍內。matrix[i][j]
包含的整數在[0, 99]
範圍內。
class Solution {
public boolean isToeplitzMatrix(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
for (int i = 1; i < m; i++){
for (int j = 1; j < n; j++){
if (matrix[i][j] != matrix[i-1][j-1])
return false;
}
}
return true;
}
}
565. 陣列巢狀
中等
索引從0
開始長度為N
的陣列A
,包含0
到N - 1
的所有整數。找到最大的集合S
並返回其大小,其中 S[i] = {A[i], A[A[i]], A[A[A[i]]], ... }
且遵守以下的規則。
假設選擇索引為i
的元素A[i]
為S
的第一個元素,S
的下一個元素應該是A[A[i]]
,之後是A[A[A[i]]]...
以此類推,不斷新增直到S
出現重複的元素。
示例 1:
輸入: A = [5,4,0,3,1,6,2]
輸出: 4
解釋:
A[0] = 5, A[1] = 4, A[2] = 0, A[3] = 3, A[4] = 1, A[5] = 6, A[6] = 2.
其中一種最長的 S[K]:
S[0] = {A[0], A[5], A[6], A[2]} = {5, 6, 2, 0}
提示:
N
是[1, 20,000]
之間的整數。A
中不含有重複的元素。A
中的元素大小在[0, N-1]
之間。
class Solution {
public int arrayNesting(int[] nums) {
Set<Integer> set = new HashSet<>();
int res = 1;
for (int i = 0; i < nums.length; i++){
if (set.contains(i)) continue;
int index = i, count = 0;
do {
set.add(index);
index = nums[index];
count++;
}while (index != i);
res = Math.max(res, count);
}
return res;
}
}
769. 最多能完成排序的塊
中等
陣列arr
是[0, 1, ..., arr.length - 1]
的一種排列,我們將這個陣列分割成幾個“塊”,並將這些塊分別進行排序。之後再連線起來,使得連線的結果和按升序排序後的原陣列相同。
我們最多能將陣列分成多少塊?
示例 1:
輸入: arr = [4,3,2,1,0]
輸出: 1
解釋:
將陣列分成2塊或者更多塊,都無法得到所需的結果。
例如,分成 [4, 3], [2, 1, 0] 的結果是 [3, 4, 0, 1, 2],這不是有序的陣列。
示例 2:
輸入: arr = [1,0,2,3,4]
輸出: 4
解釋:
我們可以把它分成兩塊,例如 [1, 0], [2, 3, 4]。
然而,分成 [1, 0], [2], [3], [4] 可以得到最多的塊數。
注意:
arr
的長度在[1, 10]
之間。arr[i]
是[0, 1, ..., arr.length - 1]
的一種排列。
class Solution {
public int maxChunksToSorted(int[] arr) {
int res = 0, max = 0;
for (int i = 0; i < arr.length; i++){
max = Math.max(arr[i], max);
if (max == i) res++; //當前最大值==當前座標
}
return res;
}
}
頻率排序
768,1,945,42,4,1014,85,15,1040,548,918,53,442,45,974,782,54,769,644,713,723,718,873,11,128,714,381,1074,121,56,33,88,123,509,695,84,665,717