参考
问题总览
| 序号 | 题目 | 完成 |
|---|
一、TopK
参考:TopK
二、区间和
参考:区间和
三、二分查找
参考:查找算法及应用
四、遍历与轮转
参考:数组遍历与翻转
五、子数组
5.1 重复子数组
参考:重复数
5.2 其他
| 序号 | 题目 | 完成 |
|---|---|---|
| 560. 和为K的子数组 | ✅ | |
| 152. 乘积最大子数组 | ||
| 209. 长度最小的子数组 | ||
| 907. 子数组的最小值之和 | ||
| 974. 和可被 K 整除的子数组 | ||
| 1438. 绝对差不超过限制的最长连续子数组 | ||
| 面试题 17.24. 最大子矩阵 | ||
| 918. 环形子数组的最大和 | ||
| 300. 最长上升子序列 | ||
| 53. 最大子序和 | ✅ |
↑↑↑ 频率大于2 ↑↑↑
// 暴力解法
class Solution {
public int subarraySum(int[] nums, int k) {
int count = 0;
for (int start = 0; start < nums.length; start++) {
int sum = 0;
for (int end = start; end >= 0; end--) {
sum += nums[end];
if (sum == k) {
count++;
}
}
}
return count;
}
}
还可以用前缀和+hashMap的方法,不写了,比较简单。
↓↓↓ 频率等于1 ↓↓↓
| 序号 | 题目 | 完成 |
|---|---|---|
| 1574. 删除最短的子数组使剩余数组有序 | ||
| 862. 和至少为 K 的最短子数组 | ||
| 918. 环形子数组的最大和 | ||
| 1493. 删掉一个元素以后全为1的最长子数组 | ||
| 1248. 统计「优美子数组」 | ||
| 643. 子数组最大平均数 I | ||
| 992. K 个不同整数的子数组 | ||
| 713. 乘积小于K的子数组 | ||
| 剑指 Offer 42. 连续子数组的最大和 |
其他
| 序号 | 题目 | 完成 |
|---|---|---|
| 连续数字 | 846. 一手顺子 | ✅ |
| 1296. 划分数组为连续数字的集合 | ✅ | |
| 1060. 有序数组中的缺失元素 | ||
| 合并数组 | 88. 合并两个有序数组 | ✅ |
| 56. 合并区间 | ✅ | |
| 4. 寻找两个正序数组的中位数 | ||
| 384. 打乱数组 | ✅ | |
| 311. 稀疏矩阵的乘法 | ||
| 73. 矩阵置零 | ||
| 85. 最大矩形 | ||
| 1497. 检查数组对是否可以被k整除 |
// 利用原数组,从后往前赋值
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int x = m - 1;
int y = n - 1;
int i = m + n - 1;
while (x >= 0 && y >= 0) {
if (nums1[x] >= nums2[y]) {
nums1[i--] = nums1[x--];
} else {
nums1[i--] = nums2[y--];
}
}
while (y >= 0) {
nums1[i--] = nums2[y--];
}
}
}
// 时间复杂度:O(m+n),每一个元素都要被访问一次
// 空间复杂度:O(1)
相同问题:846. 一手顺子
class Solution {
public boolean isPossibleDivide(int[] nums, int k) {
int len = nums.length;
// 数组的数量是k的整数倍
if (len % k != 0) {
return false;
}
// 先将所有元素出现的次数放到map里
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
int val = map.getOrDefault(num, 0);
map.put(num, val + 1);
}
// 排序
Arrays.sort(nums);
int idx = 0;
while (!map.isEmpty()) {
while (!map.containsKey(nums[idx])) {
idx++;
}
//找到第一个最小的元素
int min = nums[idx];
// 检查这个元素是否有连续的k个兄弟
for (int i = min; i < min + k; i++) {
// 发现不连续,立刻抛出异常
if (!map.containsKey(i)) {
return false;
}
// 如果存在,则更新map中的值,表示被用过了
int val = map.get(i);
if (val == 1) {
// 如果这个元素只有一个,说明要用完了,从map里删除
map.remove(i);
} else {
map.put(i, val - 1);
}
}
idx++;
}
// 检查到最后都没有不连续的,那肯定可以满足
return true;
}
}
class Solution {
int[] source;
int[] nums;
Random random;
public Solution(int[] nums) {
int len = nums.length;
source = new int[len];
this.nums = nums;
System.arraycopy(nums, 0, source, 0, len);
random = new Random();
}
public int[] reset() {
return source;
}
public int[] shuffle() {
int n = source.length;
for (int i = 0; i < n; i++) {
int next = i + random.nextInt(n - i);
int tmp = nums[i];
nums[i] = nums[next];
nums[next] = tmp;
}
return nums;
}
}
class Solution {
public int[][] merge(int[][] intervals) {
// 第一个元素升序,第二个元素也是升序
Arrays.sort(intervals, (o1,o2)->{
if(o1[0] == o2[0]){
return o1[1] - o2[1];
}
return o1[0] - o2[0];
});
List<int[]> inters = new LinkedList<>();
inters.add(new int[]{intervals[0][0],intervals[0][1]});
for(int i=1;i<intervals.length;i++){
// 当前队列中最后一个元素
int[] last = inters.get(inters.size()-1);
if(intervals[i][0] <= last[1]){
// 和前一个区间有重合,合并区间
last[1] = Math.max(last[1], intervals[i][1]);
inters.set(inters.size()-1, last);
}else{
// 和前一个区间没有重合
inters.add(new int[]{intervals[i][0], intervals[i][1]});
}
}
int[][] res = new int[inters.size()][2];
for(int i=0;i<inters.size();i++){
res[i] = inters.get(i);
}
return res;
}
}