一.移動零
力扣傳送門
給定一個數組 nums,編寫一個函數將所有 0 移動到數組的末尾,同時保持非零元素的相對順序。
示例:
輸入: [0,1,0,3,12]
輸出: [1,3,12,0,0]
說明:
必須在原數組上操作,不能拷貝額外的數組。
儘量減少操作次數。
/*
* 把數組中的 0 移到末尾
* */
public void moveZeroes(int[] nums) {
if (nums == null || nums.length == 0) return;
int n = nums.length;
int curIndex = 0;
for (int i = 0; i < n; i++) {
if (nums[i] != 0) nums[curIndex++] = nums[i];
}
while (curIndex < n) {
nums[curIndex++] = 0;
}
return;
}
二.改變矩陣維度
力扣傳送門
在MATLAB中,有一個非常有用的函數 reshape,它可以將一個矩陣重塑爲另一個大小不同的新矩陣,但保留其原始數據。
給出一個由二維數組表示的矩陣,以及兩個正整數r和c,分別表示想要的重構的矩陣的行數和列數。
重構後的矩陣需要將原始矩陣的所有元素以相同的行遍歷順序填充。
如果具有給定參數的reshape操作是可行且合理的,則輸出新的重塑矩陣;否則,輸出原始矩陣。
/*
* 重塑矩陣
* */
public int[][] matrixReshape(int[][] nums, int r, int c) {
if (nums == null || nums.length == 0) return null;
int n = nums.length;
int m = nums[0].length;
if (n * m != r * c) return null;
int newNums[][] = new int[r][c];
int row = 0, col = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (col == c) {
row++;
col = 0;
}
newNums[row++][col++] = nums[i][j];
}
}
return newNums;
}
三.找出數組中最長的連續 1
/*
* 找出數組中最長的連續 1
* 給定一個二進制數組, 計算其中最大連續1的個數。
* */
public int findMaxConsecutiveOnes(int[] nums) {
int curlen = 0;
int maxlen = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 1) curlen++;
else curlen = 0;
maxlen = Math.max(maxlen, curlen);
}
return maxlen;
}
四.有序矩陣查找
/*
* 有序矩陣查找
* */
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0) return false;
int m = matrix.length;
int n = matrix[0].length;
int row = 0;
int col = n - 1;
while (row < m && col >= 0) {
if (matrix[row][col] == target) {
return true;
} else if (matrix[row][col] > target) {
col--;
} else {
row++;
}
}
return false;
}
五.一個數組元素在 [1, n] 之間,其中一個數被替換爲另一個數,找出重複的數和丟失的數
public int[] findErrorNums(int[] nums) {
if (nums == null || nums.length == 0) return null;
int n = nums.length;
int result[] = new int[2];
for (int i = 0; i < n; ) {
if (i != nums[i] - 1) {
if (nums[nums[i] - 1] == nums[i]) {
result[0] = nums[i];
i++;
} else {
swap(nums, i, nums[i] - 1);
}
} else {
i++;
}
}
for (int i = 0; i < n; i++) {
if (nums[i] - 1 != i) {
result[1] = i + 1;
break;
}
}
return result;
}
六.優美的排列 II —數組相鄰差值的個數
題目描述:數組元素爲 1~n 的整數,要求構建數組,使得相鄰元素的差值不相同的個數爲 k。
力扣傳送門
解法一:dfs超時
public int[] constructArray(int n, int k) {//方法一:dfs超時
boolean book[] = new boolean[n + 1];
int result[] = new int[n];
HashSet<Integer> set = new HashSet<>();
dfs(book, result, 0, set, n, k);
return res;
}
int res[] = null;
public void dfs(boolean book[], int result[], int curIndex, HashSet<Integer> set, int n, int k) {
if (curIndex == n && set.size() == k) {
res = new int[n];
for (int i = 0; i < n; i++) {
res[i] = result[i];
}
return;
}
if (curIndex > n || set.size() > k) return;//剪枝
for (int i = 1; i <= n; i++) {
if (book[i]) continue;
book[i] = true;
result[curIndex] = i;
if (curIndex > 0) set.add(Math.abs(result[curIndex - 1] - i));
dfs(book, result, curIndex + 1, set, n, k);
if (curIndex > 0) set.remove(Math.abs(result[curIndex - 1] - i));
book[i] = false;
}
}
解法二:不斷反轉
若n=8初始狀態
1 2 3 4 5 6 7 8
k=1------ | 1 2 3 4 5 6 7 8 (不翻轉,直接返回)
k=2------ 1 | 8 7 6 5 4 3 2
k=3------ 1 8 | 2 3 4 5 6 7
k=4------ 1 8 2 | 7 6 5 4 3
public int[] constructArray2(int n, int k) {//方法二:不斷反轉
int a[] = new int[n];
for (int i = 0; i < n; i++) a[i] = i + 1;
int cur = 1;
for (int j = 0; j < k - 1; j++) {
reverse(a, cur, n - 1);
cur++;
}
return a;
}
public void reverse(int a[], int start, int end) {
while (start < end) {
int tmp = a[start];
a[start] = a[end];
a[end] = tmp;
start++;
end--;
}
}
七.數組的度
力扣傳送門
給定一個非空且只包含非負數的整數數組 nums, 數組的度的定義是指數組裏任一元素出現頻數的最大值。
你的任務是找到與 nums 擁有相同大小的度的最短連續子數組,返回其長度。
解法一:
public int findShortestSubArray(int[] nums) {
if (nums == null || nums.length == 0) return 0;
int num = -1;//保存目前爲止出現最高頻率的數字
int maxCount = 0;//保存目前爲止的最高頻率
int minlen = 1;//保存最高頻率數字的長度
Map<Integer, Integer> map = new HashMap<>();//保存數字的頻率
Map<Integer, Integer> mapStart = new HashMap<>();//保存數字的開始位置
for (int i = 0; i < nums.length; i++) {
if (!mapStart.containsKey(nums[i])) {//不包含 put
mapStart.put(nums[i], i);
map.put(nums[i], 0);
} else {//包含 計數
map.put(nums[i], map.get(nums[i]) + 1);
}
int count = map.get(nums[i]);
if (count > maxCount) {//當前數字的頻率大於最高頻率
num = nums[i];//更新最高頻率數字
maxCount = count;//更新頻率
minlen = i - mapStart.get(nums[i]) + 1;//更新最高頻率數字長度
}
if (count == maxCount) {//當前數字的頻率等於最高頻率
int curlen = i - mapStart.get(nums[i]) + 1;
if (curlen < minlen) {//比較長度,取短的
num = nums[i];
maxCount = count;
minlen = curlen;
}
}
}
return minlen;
}
解法二:
public int findShortestSubArray2(int[] nums) {
Map<Integer, Integer> leftmap = new HashMap<>();
Map<Integer, Integer> rightmap = new HashMap<>();
Map<Integer, Integer> countmap = new HashMap<>();
int maxCount = 0;
for (int i = 0; i < nums.length; i++) {
if (!leftmap.containsKey(nums[i])) {
leftmap.put(nums[i], i);
}
rightmap.put(nums[i], i);
int curCount = countmap.getOrDefault(nums[i], 0) + 1;
maxCount = Math.max(maxCount, curCount);
countmap.put(nums[i], curCount);
}
int minlen = nums.length;
Iterator<Map.Entry<Integer, Integer>> iterator = countmap.entrySet().iterator();//注意map遍歷方式
while (iterator.hasNext()) {
Map.Entry<Integer, Integer> entry = iterator.next();
if (entry.getValue() == maxCount) {
minlen = Math.min(minlen, rightmap.get(entry.getKey()) - leftmap.get(entry.getKey()) + 1);
}
}
return minlen;
}
八.對角元素相等的矩陣
力扣傳送門
如果一個矩陣的每一方向由左上到右下的對角線上具有相同元素,那麼這個矩陣是託普利茨矩陣。
給定一個 M x N 的矩陣,當且僅當它是託普利茨矩陣時返回 True。
解法一:
/*
* 對角元素相等的矩陣
* */
public boolean isToeplitzMatrix(int[][] matrix) {
int n = matrix.length;
int m = matrix[0].length;
for (int i = 0; i < n; i++) {
int x = i, y = 0;
int num = matrix[i][0];
while (x < n && y < m) {
if (matrix[x][y] != num) return false;
x++;
y++;
}
}
for (int j = 0; j < m; j++) {
int x = 0, y = j;
int num = matrix[0][j];
while (x < n && y < m) {
if (matrix[x][y] != num) return false;
x++;
y++;
}
}
return true;
}
解法二:
class Solution {
public boolean isToeplitzMatrix(int[][] matrix) {
Map<Integer, Integer> groups = new HashMap();
for (int r = 0; r < matrix.length; ++r) {
for (int c = 0; c < matrix[0].length; ++c) {
if (!groups.containsKey(r-c))
groups.put(r-c, matrix[r][c]);
else if (groups.get(r-c) != matrix[r][c])
return False;
}
}
return True;
}
}
九.嵌套數組
力扣傳送門
索引從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出現重複的元素。
藉助力扣官方題解的一張圖來理解:
public int arrayNesting(int[] nums) {
int n = nums.length;
boolean book[] = new boolean[n];
int maxLen = 0;
for (int i = 0; i < n; i++) {
int tmp = i;
int count = 0;
while (!book[tmp]) {
count++;
book[tmp] = true;
tmp = nums[tmp];
}
maxLen = Math.max(maxLen, count);
}
return maxLen;
}
十.最多能完成排序的塊—分割數組
力扣傳送門
數組arr是[0, 1, …, arr.length - 1]的一種排列,我們將這個數組分割成幾個“塊”,並將這些塊分別進行排序。之後再連接起來,使得連接的結果和按升序排序後的原數組相同。
我們最多能將數組分成多少塊?
/*
* 分割數組
* 分隔數組,使得對每部分排序後數組就爲有序。
* */
public int maxChunksToSorted(int[] arr) {//做法一
int n = arr.length;
boolean book[] = new boolean[n];
HashMap<Integer, Integer> map = new HashMap<>();
int count = 0;
int pre = 0;
for (int i = 0; i < arr.length; i++) {
book[arr[i]] = true;
boolean flag = true;
for (int j = pre; j <= i; j++) {//每遍歷一個arr[i]就判斷,在i位置之前的元素是否都已出現過
if (!book[j]) flag = false;
}
if (flag) {
pre = i + 1;
count++;
}
}
return count;
}
public int maxChunksToSorted2(int[] arr) {//做法二
int n = arr.length;
int right = -1;//標記最右位置
int count = 0;
for (int i = 0; i < n; i++) {
right = Math.max(right, arr[i]);
if (right == i) count++;
}
return count;
}