1. 程式人生 > 實用技巧 >LeetCode 陣列

LeetCode 陣列

基礎部分

283. 移動零

簡單

給定一個數組 nums,編寫一個函式將所有 0 移動到陣列的末尾,同時保持非零元素的相對順序。

示例:

輸入: [0,1,0,3,12]
輸出: [1,3,12,0,0]

說明:

  1. 必須在原陣列上操作,不能拷貝額外的陣列。
  2. 儘量減少操作次數。
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,它可以將一個矩陣重塑為另一個大小不同的新矩陣,但保留其原始資料。

給出一個由二維陣列表示的矩陣,以及兩個正整數rc,分別表示想要的重構的矩陣的行數和列數。

重構後的矩陣需要將原始矩陣的所有元素以相同的行遍歷順序填充。

如果具有給定引數的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. 給定矩陣的寬和高範圍在 [1, 100]。
  2. 給定的 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.

注意:

  • 輸入的陣列只包含 01
  • 輸入陣列的長度是正整數,且不超過 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]

注意:

  1. 給定陣列的長度範圍是 [2, 10000]。
  2. 給定的陣列是無序的。
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

說明:

  1. 不能更改原陣列(假設陣列是隻讀的)。
  2. 只能使用額外的 O(1) 的空間。
  3. 時間複雜度小於 O(n2) 。
  4. 陣列中只有一個重複的數字,但它可能不止重複出現一次。
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

中等

給定兩個整數 nk,你需要實現一個數組,這個陣列包含從 1nn 個不同整數,同時滿足以下條件:

① 如果這個陣列是 [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

提示:

  1. nk 滿足條件 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]"上的元素不同。

說明:

  1. matrix 是一個包含整數的二維陣列。
  2. matrix 的行數和列數均在 [1, 20]範圍內。
  3. 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,包含0N - 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}

提示:

  1. N[1, 20,000]之間的整數。
  2. A中不含有重複的元素。
  3. 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