数组
查找
二分查找
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| int search(int* nums, int numsSize, int target){ int left = 0; int right = numsSize-1; int middle = 0; while(left<=right) { middle = (left+right)/2; if(nums[middle] > target) { right = middle-1; } else if(nums[middle] < target) { left = middle+1; } else if(nums[middle] == target){ return middle; } } return -1; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| int search(int* nums, int numsSize, int target){ int length = numsSize; int left = 0; int right = length; int middle = 0; while(left < right){ int middle = left + (right - left) / 2; if(nums[middle] < target){ left = middle + 1; }else if(nums[middle] > target){ right = middle ; }else{ return middle; } } return -1; }
|
JAVA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public int search(int[] nums, int target) { if (target < nums[0] || target > nums[nums.length - 1]) { return -1; } int left = 0, right = nums.length - 1; while (left <= right) { int mid = left + ((right - left) >> 1); if (nums[mid] == target) return mid; else if (nums[mid] < target) left = mid + 1; else if (nums[mid] > target) right = mid - 1; } return -1; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { public int search(int[] nums, int target) { int left = 0, right = nums.length; while (left < right) { int mid = left + ((right - left) >> 1); if (nums[mid] == target) return mid; else if (nums[mid] < target) left = mid + 1; else if (nums[mid] > target) right = mid; } return -1; } }
|
python
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Solution: def search(self, nums: List[int], target: int) -> int: left, right = 0, len(nums) - 1
while left <= right: middle = left + (right - left) // 2 if nums[middle] > target: right = middle - 1 elif nums[middle] < target: left = middle + 1 else: return middle return -1
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Solution: def search(self, nums: List[int], target: int) -> int: left, right = 0, len(nums)
while left < right: middle = left + (right - left) // 2
if nums[middle] > target: right = middle elif nums[middle] < target: left = middle + 1 else: return middle return -1
|
移除元素
暴力方法
JAVA
双指针法
JAVA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { public int removeElement(int[] nums, int val) { int slowIndex = 0; for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) { if (nums[fastIndex] != val) { nums[slowIndex] = nums[fastIndex]; slowIndex++; } } return slowIndex; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
class Solution { public int removeElement(int[] nums, int val) { int left = 0; int right = nums.length - 1; while(right >= 0 && nums[right] == val) right--; while(left <= right) { if(nums[left] == val) { nums[left] = nums[right]; right--; } left++; while(right >= 0 && nums[right] == val) right--; } return left; } }
|
长度最小的子数组
暴力方法
滑动窗口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution {
public int minSubArrayLen(int s, int[] nums) { int left = 0; int sum = 0; int result = Integer.MAX_VALUE; for (int right = 0; right < nums.length; right++) { sum += nums[right]; while (sum >= s) { result = Math.min(result, right - left + 1); sum -= nums[left++]; } } return result == Integer.MAX_VALUE ? 0 : result; } }
|
相关题目
904 水果成篮
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits
表示,其中 fruits[i]
是第 i
棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
- 你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
- 你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
- 一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits
,返回你可以收集的水果的 最大 数目。
示例 1:
1 2 3
| 输入:fruits = [1,2,1] 输出:3 解释:可以采摘全部 3 棵树。
|
示例 2:
1 2 3 4
| 输入:fruits = [0,1,2,2] 输出:3 解释:可以采摘 [1,2,2] 这三棵树。 如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。
|
示例 3:
1 2 3 4
| 输入:fruits = [1,2,3,2,2] 输出:4 解释:可以采摘 [2,3,2,2] 这四棵树。 如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。
|
示例 4:
1 2 3
| 输入:fruits = [3,3,3,1,2,1,1,2,3,3,4] 输出:5 解释:可以采摘 [1,2,1,1,2] 这五棵树。
|
分析
该题就是要寻找子序列,但是题干写的很抽象,用人话就是说要寻找最多只包含两种元素的最长子串,然后返回长度。为什么只能有两种元素呢,因为题目描述里面说只有两个篮子。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Solution { public int totalFruit(int[] fruits) { int left = 0; int right = 0; int result = 0; int l = fruits[left]; int r = fruits[right]; while(right < fruits.length) { if(fruits[right] == l || fruits[right] == r) { result = Math.max(result,right - left + 1); right++;
} else { left = right - 1; l = fruits[left]; while(left >= 1 && fruits[left - 1] == l) { left--; } r = fruits[right]; result = Math.max(result,right - left + 1); } } return result; } }
|
76 最小覆盖子串
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
注意:
- 对于
t
中重复字符,我们寻找的子字符串中该字符数量必须不少于 t
中该字符数量。
- 如果
s
中存在这样的子串,我们保证它是唯一的答案。
示例 1:
1 2 3
| 输入:s = "ADOBECODEBANC", t = "ABC" 输出:"BANC" 解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
|
示例 2:
1 2 3
| 输入:s = "a", t = "a" 输出:"a" 解释:整个字符串 s 是最小覆盖子串。
|
示例 3:
1 2 3 4
| 输入: s = "a", t = "aa" 输出: "" 解释: t 中两个字符 'a' 均应包含在 s 的子串中, 因此没有符合条件的子字符串,返回空字符串。
|
分析
76. 最小覆盖子串 - 力扣(Leetcode)
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| public static String minWindow(String s, String t) { if(s == null || s.length() == 0 || t == null || t.length() == 0) { return ""; } int l = 0; int r = 0; int[] need = new int [200]; int size = Integer.MAX_VALUE; int count = t.length(); int start = 0; for(int i = 0;i < t.length();i++) { need[t.charAt(i)]++; } while(r < s.length()) { char c = s.charAt(r); if(need[c] > 0) { count--; } need[c]--; if(count == 0)
{ while(true) { c = s.charAt(l); if(need[c] == 0) { break; } need[c] += 1; l++;
} if(r - l + 1 < size) { size = r - l + 1; start = l; } need[s.charAt(l)]++; l++; count++; } r++; } return size == Integer.MAX_VALUE ? "" : s.substring(start,start + size); }
|
螺旋矩阵
相关题目
59 螺旋矩阵II
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class Solution { public int[][] generateMatrix(int n) { int loop = 0; int[][] res = new int[n][n]; int start = 0; int count = 1; int i, j;
while (loop++ < n / 2) { for (j = start; j < n - loop; j++) { res[start][j] = count++; }
for (i = start; i < n - loop; i++) { res[i][j] = count++; }
for (; j >= loop; j--) { res[i][j] = count++; }
for (; i >= loop; i--) { res[i][j] = count++; } start++; }
if (n % 2 == 1) { res[start][start] = count; }
return res; } }
|
54 螺旋矩阵
给你一个 m
行 n
列的矩阵 matrix
,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例 1:

1 2
| 输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]
|
示例 2:

1 2
| 输入: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]
|
分析
与59.螺旋矩阵II不同的是:前题中的螺旋矩阵是正方形,只有正方形的边长n一个边界条件,而本题中,需要考虑长方形的长和宽(m行和n列)两个边界条件。自然,m可以等于n,即前题可视为本题在m==n的特殊情况。
我们从最一般的情况开始考虑,与59.螺旋矩阵II题解对比起来,m和n的带入,主要引来两方面的差异:
- loop的计算: 本题的loop计算与59.螺旋矩阵II算法略微差异,因为存在rows和columns两个维度,可自行分析,loop只能取min(rows, columns),例如rows = 5, columns = 7,那loop = 5 / 7 = 2
- mid的计算及填充: 1、同样的原理,本题的mid计算也存在上述差异; 2、 如果min(rows, columns)为偶数,则不需要在最后单独考虑矩阵最中间位置的赋值 如果min(rows, columns)为奇数,则矩阵最中间位置不只是[mid][mid],而是会留下来一个特殊的中间行或者中间列,具体是中间行还是中间列,要看rows和columns的大小,如果rows > columns,则是中间列,相反,则是中间行
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| ArrayList<Integer> list = new ArrayList<>(); int rows = matrix.length; int columns = matrix[0].length; int i,j; int startx = 0, starty = 0; int loop = Math.min(rows, columns) / 2;
int mid = loop; int offset = 1;
while(loop > 0) { for(j = starty;j < columns - offset;j++) { list.add(matrix[startx][j]); } for(i = startx;i < rows - offset;i++) { list.add(matrix[i][j]); } for(;j >= offset;j--) { list.add(matrix[i][j]); } for(;i >= offset;i--) { list.add(matrix[i][j]); } startx++; starty++; loop--; offset++; } if(Math.min(rows,columns) % 2 != 0) { if(rows > columns) { for(i = mid;i <= mid + rows - columns;i++) { list.add(matrix[i][mid]); } } else { for(j = mid;j <= mid + columns - rows;j++) { list.add(matrix[mid][j]); } } } return list;
|
29 顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
示例 1:
1 2
| 输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]
|
示例 2:
1 2
| 输入: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]
|
分析
该题目的矩阵行数和列数可以不相等,因此和54题大致是一样的,关键要处理剩下来的一行或一列
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| public int[] spiralOrder(int[][] matrix) { int rows = matrix.length; if(rows == 0) { return new int[0]; } int columns = matrix[0].length; int []ans = new int [rows * columns]; int i,j; int count = 0; int startx = 0; int starty = 0; int loop = Math.min(rows,columns) / 2; int mid = loop; int offset = 1; while(loop > 0) { for(j = starty;j < columns - offset;j++) { ans[count] = matrix[startx][j]; count++; } for(i = startx;i < rows - offset;i++) { ans[count] = matrix[i][j]; count++; } for(;j >= offset;j--) { ans[count] = matrix[i][j]; count++; } for(;i >= offset;i--) { ans[count] = matrix[i][j]; count++; } startx++; starty++; offset++; loop--; } if(Math.min(rows,columns) % 2 != 0) { if(rows > columns) { for(i = mid;i <= mid + rows - columns;i++) { ans[count] = matrix[i][mid]; count++; } } else { for(j = mid;j <= mid + columns - rows;j++) { ans[count] = matrix[mid][j]; count++; } } } return ans;
|
