有序数组的平方
题目链接:. - 力扣(LeetCode)
文章讲解:代码随想录
同上篇一致运用双指针法
原理:
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
此时可以考虑双指针法了,left 指向起始位置,right 指向终止位置。
每次比较两个指针对应的数,选择较大的那个逆序放入答案并移动指针。这种方法无需处理某一指针移动至边界的情况
class Solution {
public int[] sortedSquares(int[] nums) {
int left=0;
int right=nums.length-1;
int[] a=new int[nums.length];//a是平方后存储的数组
for(int k=nums.length-1;k>=0;k--) {
//两端的平方值比较大小,同时移动指针
int i=nums[left]*nums[left];
int j=nums[right]*nums[right];
if(i>j) {
a[k]=i;
left++;
}
else {
a[k]=j;
right--;
}
}
return a;
}
}
长度最小的子数组
题目链接:. - 力扣(LeetCode)
文章讲解:代码随想录
滑动窗口:
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
定义两个指针 start和 end 分别表示子数组(滑动窗口窗口)的开始位置和结束位置,维护变量 sum存储子数组中的元素和。
类似这种:
初始做法:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int n=nums.length-1;
int i=0,j=0,l=0,sum=nums[0];
while(i<=j){
if(sum<target&&j<n)
{
j++;
sum+=nums[j];
}
else if(sum>=target) {
if(l>j-i+1||l==0) {
l=j-i+1;
}
sum-=nums[i];
i++;
}
else {
break;
}
}
return l;
}
}
利用 i 和 j 互相追逐特性设计循环,大致思想当总和超过时记录长度并移动 i ,总和小于时移动 j 扩展窗口,缺点是 i 与 j 容易越界,需多加条件作为限制。
参考代码:
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;
}
}
改进:
1.将长度 l 定义为最大值(Integer.MAX_VALUE),返回值时进行是否为最大值的判断,可以在循环中减少一层判断
2.运用已有函数Math.min(),省去一层if判断:
if(l>j-i+1||l==0) {
l=j-i+1;
}
改为
l=Math.min(l, j-i+1);
3.总体思想是将窗口右指针移动作为循环条件,每一轮迭代,将 nums[right]加到 sum,如果 sum≥s,则更新子数组的最小长度(此时子数组的长度是 right−left+1),然后将 nums[left]从 sum中减去并将 left右移,直到 sum<s,在此过程中同样更新子数组的最小长度。在每一轮迭代的最后,将right右移。
可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。
螺旋矩阵II
题目链接:. - 力扣(LeetCode)
文章讲解:代码随想录
自己想的:
思路:
每一圈为一个循环,每个颜色地块总数为第二层循环,即每个地块总数的数量一致情况下,
通过计算每个地块位置及其数值进行赋值
另奇数矩阵需要单独对中心进行赋值。
class Solution {
public int[][] generateMatrix(int n) {
int[][] a=new int[n][n];
int sum=0;
for(int i=0;i<(n+1)/2;i++) {
int j=n-1-2*i;
for(int k=0;k<j;k++) {
a[i][i+k]=0*j+1+k+sum;
a[i+k][n-i-1]=1*j+1+k+sum;
a[n-i-1][n-i-k-1]=2*j+1+k+sum;
a[n-k-i-1][i]=3*j+1+k+sum;
}
sum+=4*j;
}
if(n%2!=0) {
a[n/2][n/2]=n*n;
}
return a;
}
}
参考答案:
class Solution {
public int[][] generateMatrix(int n) {
int loop = 0; // 控制循环次数
int[][] res = new int[n][n];
int start = 0; // 每次循环的开始点(start, start)
int count = 1; // 定义填充数字
int i, j;
while (loop++ < n / 2) { // 判断边界后,loop从1开始
// 模拟上侧从左到右
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;
}
}
小技巧:
1.int最大值:Integer.MAX_VALUE,可以在变量不适合赋值0时进行赋值
2.遍历二维数组:
for(int i=0;i<n;i++) {
System.out.println(Arrays.toString(key[i]));
}
3.获取绝对值:Math.abs();
4.判断奇数偶数:
if (number%2==0){
System.out.println(number+"是偶数");
}else {
System.out.println(number+"是奇数");
}