今日任务
977.有序数组的平方
如果用快速排序和时间复杂度为O(nlogn),双指针时间复杂度为O(n)
暴力解法
Java有单独的排序函数--sort()
双指针解法
思路
由于改数组中含有负数,所以数组左右两边的数大,中间小
更新新的数组的时候,按照下标从小到大更新就可以了
class Solution {
public int[] sortedSquares(int[] nums) {
int[] result=new int[nums.length];
k=nums.length-1;//先取最大值
for(int i=0,j=nums.length-1;i<=j;){//不写i++,j--,也可以用for,因为先要判断大小,才能进行下去
//因为i和j最终都要指向一个元素后停止循环,但i=j这个元素也要取到,所以循环条件是i<=j
if(nums[i]*nums[i]>nums[j]*nums[j]){
result[k--]=nums[i]*nums[i];
i++;
}
//排除相等情况,因为用哪种表示都可以
else{
result[k--]=nums[j]*nums[j];
j--;
}
}
return result;
}
}
209.长度最小的子数组
依旧是双指针解法
暴力解法
即把所以情况列举出来
class Solution {
int minSubArrayLen(int s, int[] nums) {
int result = INT32_MAX; // 最终的结果
int sum = 0; // 子序列的数值之和
int subLength = 0; // 子序列的长度
for (int i = 0; i < nums.length; i++) { // 设置子序列起点为i
sum = 0;
for (int j = i; j < nums.length; j++) { // 设置子序列终止位置为j
sum += nums[j];
if (sum >= s) { // 一旦发现子序列和超过了s,更新result
subLength = j - i + 1; // 取子序列的长度
result = result < subLength ? result : subLength;
break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
}
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return result == INT32_MAX ? 0 : result;
}
}
滑动窗口--双指针
思路
也同样是用一个for循环解决两个for循环的事情
关于滑动窗口的指针
如果for循环里的j表示的是起始位置,那么终止位置的指针也需要一个一个遍历,这本质上跟暴力没区别,所以j必须是终止位置
何时移动起始位置,当集合里的元素和大于等于s时,要保证下一个不能继续s,这时移动起始位置去收集不同长度区间里的和,所以如何移动起始位置是这道题的重点
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int i=0,j=0,sum=0,SubL=0,result=Integer.MAX_VALUE;
for(;j<nums.length;j++){
sum+=nums[j];
while(sum>=target){
SubL=j-i+1;
result=Math.min(result,SubL);
sum-=nums[i];
i++;
}
}
if (result == Integer.MAX_VALUE) {
return 0; // 或者返回 -1,表示没有找到
}
return result;
}
}
59.螺旋矩阵Ⅱ
方法一
每条边的处理规则应该统一:左闭右开或者左闭右闭
class Solution {
public int[][] generateMatrix(int n) {
int startx=0,starty=0,offset=1,count=1;
int i,j;
int[][]nums=new int[n][n];
while(offset<=n/2)//边长除2就是圈数,n若为奇数,最后一圈直接赋给数组就可以
{
for(j=starty;j<n-offset;j++)//固定行标,改变列标,用n-offset表示这一行的终止位置(下一圈的终止位置应该比上一行少一个元素)
{
nums[startx][j]=count++;
}
for(i=startx;i<n-offset;i++)
{
nums[i][j]=count++;
}
for(;j>starty;j--)
{
nums[i][j]=count++;
}
for(;i>startx;i--)
{
nums[i][j]=count++;
}
startx++;
starty++;
offset++;
}
if (n % 2 == 1) { // n 为奇数时,单独处理矩阵中心的值
nums[startx][starty] = count;
}
return nums;
}
}
方法二
public class 螺旋填数mn {
public static void FillNum(int m, int n)
{
int[][] arr = new int[m][n];// 初始化
int x = 0;// 行数
int y = 0;// 列数
int ctrl = 0;// 方向控制变量
int[][] deriction = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };// 创建方向数组
for (int i = 1; i <= m * n; i++) {
arr[x][y] = i;// 填数
//依照预定方向的下一个坐标
int x2 = x + deriction[ctrl][0];
int y2 = y + deriction[ctrl][1];
//解法一:
if ((x == 0 && y == n - 1) || (y == n - 1 && x == m - 1) || (x == m - 1 && y == 0)
|| arr[x2][y2] != 0) {
// 方向控制判断语句
ctrl= (ctrl+1)%4;// 更改方向
}
//解法二:
// if ((y2 == n) || (x2 == m) || y2<0 || x2<0
// || arr[x2][y2] != 0) {
// // 方向控制判断语句
// ctrl= (ctrl+1)%4;// 更改方向
// }
x += deriction[ctrl][0];
y += deriction[ctrl][1];
}
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.printf("%3d ",arr[i][j]);
}
System.out.println();
}
}
public static void main(String[] args)
{
FillNum(3, 3);
}
}