1.排序
十大排序是最基本的也是我们必须要掌握的算法。下次逐步更新
2.双指针算法
在许多的数组问题当中都用到了双指针的概念,我理解的双指针包括快慢指针(向一个方向遍历,一快一慢。),前后指针(遍历方向相反,二分法其实也算是双指针),包括滑动窗口。
快慢指针:
下面咱们上题:力扣27:移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
class Solution {
public int removeElement(int[] nums, int val) {
int r = 0;
//快n慢r指针
for(int n = 0 ; n < nums.length ; n++){
//遍历数组中的元素和目标值比较
if (nums[n] != val ){
/*
1.如果不相等(不需要移除) 快慢指针前进
2.如果相等(需要移除),n前进 r不动,直到n指针碰到了不需要移除的元素,
覆盖r目前指向的需要移除的元素,然后同时前进
3.如果右边界元素为需要移除的元素,此时r不动 返回的r是处理后数组的新长度
*/
nums[r] = nums[n];
r++;
}
}
return r;
}
}
前后指针
力扣977:有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。(这里的非递减就是递增)
解析:根据题意可知递增数组的平方的每个元素的大小肯定是两边的大于中间的(左边为负数时)
class Solution {
public int[] sortedSquares(int[] nums) {
//后指针,遍历方向向左
int k = nums.length-1;
int r = nums.length-1;
//前指针,遍历方向向右
int j = 0;
int[] res = new int[k+1];
while(j<=k){
if(nums[k]*nums[k] > nums[j]*nums[j]){
res[r--] = nums[k]*nums[k];
k--;
}else{
res[r--] = nums[j]*nums[j];
j++;
}
}
return res;
}
}
滑动窗口
滑动窗口的要点就是根据题目要求动态的维护一个符合题意的数组区间(窗口)
力扣209:长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
//滑动窗口--双指针
int l = 0;
int len = nums.length ;
int sum = 0;
int res = Integer.MAX_VALUE;
for(int f = 0 ; f < len ; f++){
sum += nums[f];
//这里维护窗口 满足条件的最小的窗口大小就就是答案
while(sum >= target){
res = (res > (f - l +1)) ? (f - l +1 ) : res ;
sum -= nums[l++];
}
}
return res == Integer.MAX_VALUE ? 0 : res;
}
}
3模拟问题
没有特定的解题方案。考察对于代码编写的熟练度。
力扣59:螺旋矩阵II
题解:
class Solution {
public int[][] generateMatrix(int n) {
//循环不变量
int[][] res = new int[n][n];
//定义旋转起点
int startX = 0;
int startY = 0;
//定义旋转次数
int time = n/2;
//结果起点 1 到 n*n
int x= 1;
//定义每次循环的边长
int step = n-1;
while(time>0){
//旋转方向 右下左上
for(int i = 0 ; i < step; i++){
res[startX][startY++] = x++;
}
//下
for(int i = step ; i < 2*step; i++){
res[startX++][startY] = x++;
}
//左
for(int i = 2*step ; i < 3*step; i++){
res[startX][startY--] = x++;
}
//上
for(int i = 3*step ; i < 4*step; i++){
res[startX--][startY] = x++;
}
//第一个循环完毕
time--;
//起点加一
startX+=1;
startY+=1;
//边长减2
step-=2;
}
//如果n不是2的倍数,中心点需要手动填充
if(n%2!=0){
res[n/2][n/2] = n*n;
}
return res;
}
}