Array brush questions
Array method summary:
- Dichotomy : the premise is that the array must be ordered
- Double pointer method : complete the work of two for loops under one for loop through a fast pointer and a slow pointer
- Sliding window : constantly adjust the starting position of the subsequence according to the current subsequence and size
- Simulation behavior : such as a spiral matrix, write code according to the requirements of the topic
Arrays
Common APIs for tool classes in Java :
int[] arr = new int[] {
1, 2, 3, 4 };
// 数组打印 (调试时方便)
Arrays.toString(arr); // [1, 2, 3, 4]
// 数组排序
Arrays.toString(arr);
// 二分搜索 (数组必须有序)
Arrays.binarySearch(arr, 2);
// 数组复制 (左闭右开)
int[] newArr = Arrays.copyOfRange(arr, 0, arr.length);
// 比较两个数组
Arrays.equals(arr, newArr);
// 数组全部元素赋值
Arrays.fill(arr, -1);
// 快速生成 List
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = List.of(1, 2, 3);
two points
binary search*
Subject: 704. Binary Search
Given n
an ordered (ascending) integer array of elements nums
and a target value target
, write a function to search nums
for target
, and return the subscript if the target value exists, otherwise return -1
.
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
The premise of using dichotomy: the array is ordered.
Java source code dichotomy: suitable for finding a single value
public int search(int[] nums, int target) {
int l = 0, r = nums.length - 1;
while (l <= r) {
int mid = (l + r) >> 1;
if (nums[mid] < target) l = mid + 1;
else if (nums[mid] > target) r = mid - 1;
else return mid;
}
return - 1;
}
y total template 1: can be used to find the left boundary
public int search(int[] nums, int target) {
int l = 0, r = nums.length - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (nums[mid] >= target) r = mid;
else l = mid + 1;
}
if (nums[l] == target) return l;
return - 1;
}
y total template 2: can be used to find the right boundary
public int search(int[] nums, int target) {
int l = 0, r = nums.length - 1;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (nums[mid] <= target) l = mid;
else r = mid - 1;
}
if (nums[l] == target) return l;
return -1;
}
search caret position
Given a sorted array and a target value, find the target value in the array and return its index. If the target value does not exist in the array, returns the position where it will be inserted in order.
Please use an algorithm with a time complexity O(logn)
of .
输入: nums = [1,3,5,6], target = 5
输出: 2
The Java source code is divided into two parts:
public int searchInsert(int[] nums, int target) {
int l = 0, r = nums.length - 1;
while (l <= r) {
int mid = (l + r) >> 1;
if (nums[mid] > target) r = mid - 1;
else if (nums[mid] < target) l = mid + 1;
else return mid;
}
return l;
}
y total template:
public int searchInsert(int[] nums, int target) {
int l = 0, r = nums.length - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (nums[mid] >= target) r = mid;
else l = mid + 1;
}
if (nums[l] < target) return l + 1;
return l;
}
Find the first and last position of an element in a sorted array*
Topic: 34. Find the first and last position of an element in a sorted array - LeetCode
You are given an array of integers in non-decreasing order nums
, and a target value target
. Please find out where the given target value starts and ends in the array. Returns
if the target value does not exist in the array . You must design and implement an algorithm of to solve this problem.target
[-1, -1]
O(log n)
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
Find the left boundary by two points + find the right boundary by two points:
public int[] searchRange(int[] nums, int target) {
if (nums.length == 0) return new int[] {
-1, -1 };
// 二分找左边界 - y总模板1
int l = 0, r = nums.length - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (nums[mid] >= target) r = mid;
else l = mid + 1;
}
if (nums[l] != target) return new int[] {
-1, -1 };
int lb = l;
// 二分找右边界 - y总模板2
l = 0; r = nums.length - 1;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (nums[mid] <= target) l = mid;
else r = mid - 1;
}
int rb = l;
return new int[] {
lb, rb };
}
Other ideas: Divide to find a value that satisfies the condition, and spread the search boundary to the left and right (the worst possible O(n))
square root of x
Given a non-negative integer x
, compute and x
return the arithmetic square root of .
输入:x = 4
输出:2
Floating-point dichotomy: can output numbers after the decimal point (the situation is not as complicated as integer dichotomy, and it is easy to write)
public int mySqrt(int x) {
double l = 1, r = x;
while (r - l > 1e-6) {
// 设置一个精度
double mid = (l + r) / 2;
if (mid * mid <= x) l = mid;
else r = mid;
}
return (int) r;
}
Integer bisection: use x / mid
anti- overflow
public int mySqrt(int x) {
int l = 1, r = x;
while (l <= r) {
int mid = l + (r - l) / 2;
if (mid < x / mid) l = mid + 1;
else if (mid > x / mid) r = mid - 1;
else return mid;
}
return r;
}
effective perfect square
Given a positive num
integer , write a function that returns if num
is a perfect square, true
otherwise false
.
输入:num = 16
输出:true
The Java source code is divided into two parts:
class Solution {
public boolean isPerfectSquare(int num) {
int l = 1, r = num;
while (l <= r) {
int mid = (l + r) >> 1;
if (num / mid < mid) r = mid - 1;
else if (num / mid > mid) l = mid + 1;
else return num % mid == 0;
}
return false;
}
}
y total two points:
class Solution1 {
public boolean isPerfectSquare(int num) {
int l = 1, r = num;
while (l < r) {
int mid = (l + r) >> 1;
if (num / mid <= mid) r = mid;
else l = mid + 1;
}
return (num / l == l) && (num % l == 0);
}
}
double pointer
The double-pointer chapter contains all the questions here, refer to: [Code Random Record] Double-pointer method for brushing questions
remove element
Title: 27. Removing elements
Remove duplicates in sorted array
Fast and slow pointers can be used to delete duplicate items.
moving zero
Title: 283. Moving Zero - LeetCode
compare strings with backspaces
Square of sorted array
Topic: Squaring an ordered array
sliding window
The smallest subarray
Title: 209. Minimum Length Subarray
Given n
an array of positive integers and a positive integer target
. Find the contiguous subarray
with the smallest length satisfying ≥ target
its , and return its length. If there is no subarray that meets the condition, return it . [numsl, numsl+1, ..., numsr-1, numsr]
0
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
Sliding window (two pointer):
public int minSubArrayLen(int target, int[] nums) {
int res = Integer.MAX_VALUE, sum = 0;
for (int l = 0, r = 0; r < nums.length; r++) {
sum += nums[r];
while (sum >= target) {
// 收缩左窗口
res = Math.min(res, r - l + 1);
sum -= nums[l++];
}
}
return res % Integer.MAX_VALUE;
}
fruit basket
Topic: 904. Fruit Basket - LeetCode
You are visiting a farm with a row of fruit trees planted from left to right. These trees are fruits
represented , where is the type offruits[i]
fruit on the th i
tree . You want to collect as many fruits as possible. However, the owner of the farm has set some strict rules that you must follow to pick the fruit:
- You only have two baskets, and each basket can only hold a single type of fruit. There is no limit to the total amount of fruit each basket can hold.
- You can choose any tree to start picking, and you must pick exactly one fruit from each tree (including the tree where you started picking) . Fruit picked should match the type of fruit in the basket. Each time you pick, you will move right to the next tree and continue picking.
- Once you get to a tree and the fruit doesn't fit the type of fruit in your basket, then you have to stop picking.
Given an array of integersfruits
, return the maximum .
输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。
输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。
HashMap
+ Sliding window:
public int totalFruit(int[] fruits) {
int res = 0;
Map<Integer, Integer> map = new HashMap<>(2);
for (int l = 0, r = 0; r < fruits.length; r++) {
map.put(fruits[r], map.getOrDefault(fruits[r], 0) + 1);
// 滑动窗口内水果种类 > 2 时
while (map.size() > 2) {
map.put(fruits[l], map.get(fruits[l]) - 1);
if (map.get(fruits[l]) == 0) map.remove(fruits[l]);
l++;
}
res = Math.max(res, r - l + 1);
}
return res;
}
Use array optimization HashMap
:
public int totalFruit(int[] fruits) {
int[] map = new int[fruits.length];
int res = 0, size = 0; // 当前水果种类
for (int l = 0, r = 0; r < fruits.length; r++) {
if (map[fruits[r]] == 0) size++;
map[fruits[r]]++;
// 滑动窗口内水果种类 > 2 时
while (size > 2) {
map[fruits[l]]--;
if (map[fruits[l]] == 0) size--;
l++;
}
res = Math.max(res, r - l + 1);
}
return res;
}
minimum covering substring
You are given a string s
, a string t
. s
Returns t
the smallest substring covering all characters in . s
Returns an empty string if no t
substring covering all characters exists in ""
.
Note :
- For repeated characters
t
in , the number of characters in the substring we are looking for must be no less thant
the number of characters in . - If such a substring exists
s
in , we guarantee that it is the only answer.
Sliding window + double pointer:
public String minWindow(String s, String t) {
int[] map = new int[128]; // 记录字符出现次数
for (char c : t.toCharArray()) map[c]--; // map[c]==-1 表示需要 1 个字符 c
int count = 0; // 总共需要的字符数, count==t.length() 则满足最小覆盖子串
// 记录最小覆盖串开始的 index 和 size
int start = 0, size = Integer.MAX_VALUE;
for (int l = 0, r = 0; r < s.length(); r++) {
if (map[s.charAt(r)] < 0) count++; // 需要当前访问的字符
map[s.charAt(r)]++; // 访问当前字符
// 收缩窗口: map[c] > 0 表示不需要字符 c, 左指针可以往右移动
while (l < r && map[s.charAt(l)] > 0) map[s.charAt(l++)]--;
// 满足条件 并且 当前覆盖串长度更小, 则记录
if (count == t.length() && r - l + 1 < size) {
size = r - l + 1;
start = l;
}
}
return size == Integer.MAX_VALUE ? "" : s.substring(start, start + size);
}
simulation
Spiral Matrix II*
Title: 59. Spiral Matrix II
Given a positive integer n
, generate 1
a squaren2
matrix containing all elements of to spirally arranged in clockwise order .n x n
matrix
输入:n = 3
输出:
[[1,2,3],[8,9,4],[7,6,5]]
Simulation: bottom right, top left, four directions in order
- Before leaving: judge whether it crosses the boundary and whether it has been visited.
- Finished: Mark the current location as visited.
- The first position needs to be walked manually.
public int[][] generateMatrix(int n) {
int[][] res = new int[n][n];
int i = 0, j = 0, cur = 2;
res[0][0] = 1; // 手动走第一个位置
while (cur <= n * n) {
while (j < n - 1 && res[i][j + 1] == 0) res[i][++j] = cur++; // 右
while (i < n - 1 && res[i + 1][j] == 0) res[++i][j] = cur++; // 下
while (j > 0 && res[i][j - 1] == 0) res[i][--j] = cur++; // 左
while (i > 0 && res[i - 1][j] == 0) res[--i][j] = cur++; // 上
}
return res;
}
spiral matrix
Title: 54. Spiral Matrix - LeetCode
Given m
a n
matrix of rows and columns matrix
, please return all elements in the matrix in a clockwise spiral order.
输入:matrix =
[[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
public List<Integer> spiralOrder(int[][] matrix) {
final int INF = 0x3f3f3f3f; // 无穷大标记为已访问
List<Integer> res = new ArrayList<>();
res.add(matrix[0][0]); // 第一个元素手动处理
matrix[0][0] = INF;
int m = matrix.length, n = matrix[0].length;
int k = m * n;
int x = 0, y = 0;
while (k-- > 1) {
while (y < n - 1 && matrix[x][y + 1] != INF) {
// 右
res.add(matrix[x][++y]);
matrix[x][y] = INF;
}
while (x < m - 1 && matrix[x + 1][y] != INF) {
// 下
res.add(matrix[++x][y]);
matrix[x][y] = INF;
}
while (y > 0 && matrix[x][y - 1] != INF) {
// 左
res.add(matrix[x][--y]);
matrix[x][y] = INF;
}
while (x > 0 && matrix[x - 1][y] != INF) {
// 上
res.add(matrix[--x][y]);
matrix[x][y] = INF;
}
}
return res;
}
print matrix clockwise
Topic: Sword Pointing to Offer 29. Print Matrix Clockwise - LeetCode
Enter a matrix and print each number in clockwise order from the outside to the inside.
输入:matrix =
[[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
This question is the same as spiral matrix.
public int[] spiralOrder(int[][] matrix) {
if (matrix.length == 0) return new int[] {
};
final int INF = 0x3f3f3f3f; // 无穷大标记为已访问
int m = matrix.length, n = matrix[0].length;
int[] res = new int[m * n];
res[0] = matrix[0][0]; // 第一个元素手动处理
matrix[0][0] = INF;
int x = 0, y = 0, k = 1; // k 从第二个元素开始放
while (k < m * n) {
while (y < n - 1 && matrix[x][y + 1] != INF) {
res[k++] = matrix[x][++y];
matrix[x][y] = INF;
}
while (x < m - 1 && matrix[x + 1][y] != INF) {
res[k++] = matrix[++x][y];
matrix[x][y] = INF;
}
while (y > 0 && matrix[x][y - 1] != INF) {
res[k++] = matrix[x][--y];
matrix[x][y] = INF;
}
while (x > 0 && matrix[x - 1][y] != INF) {
res[k++] = matrix[--x][y];
matrix[x][y] = INF;
}
}
return res;
}