一、长度最小的子数组
解题思路
采用滑动窗口方法,其实也是双指针法的一种,只不过用滑动窗口能够更为形象地描述这个方法的动态过程。
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
(1)在该题中,i 定为初始位置,j 定为终止位置。首先设置一个for循环。
(2)并在该for循环中,从初始位置开始,先对num[j]依次相加,用sum记录累加和,直至sum>=target值。
(3)然后再用while循环进行如下操作。当sum>=target时,首先记录累加和为sum的子数组长度,然后sum - =num [i],i 向数组下一位移动,即i=i+1。这样就完成了滑动操作。继续这样的操作直至sum<target,此时sum的长度最小。
具体代码如下:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int i=0,result=Integer.MAX_VALUE;
int sum=0;
for(int j=0;j<nums.length;j++){
sum+=nums[j];
while(sum>=target){
int currentL=j-i+1;
result=Math.min(result,currentL);
sum-=nums[i];
i++;
}
}
//如果result没有被更改过,说明数组中所有值加起来仍然小于target,所以实际返回值应该为0
return result == Integer.MAX_VALUE ? 0 : result;
}
}
看到本题我的第一想法是采用双层for循环进行计算,但是for循环中具体怎么实现还是不太清楚,于是看了b站上carl哥的视频讲解。滑动指针的思路确实不太好理解,但是和代码以及数组的动态变化结合到一起就比较容易接受。
二、.螺旋矩阵II
螺旋矩阵最主要的是边界条件的设置。边界是动态变化的,并且是从外往里螺旋赋值。
loop为圈数,每旋转一圈,loop+1。
x,y为每一圈旋转的初始位置。
由于每次循环赋值时的区间为左闭右开区间,所以设置offset。循环终结条件为n-offset,也就是右边界不赋值。offset初始值为1,每循环一圈,offset+1。
代码如下:
class Solution {
public int[][] generateMatrix(int n) {
int i,x=0,y=0,j,loop=1,count=1,offset=1;
int[][] result=new int[n][n];
while(loop<=n/2){
//顶部
for(j=y;j<n-offset;j++){
result[x][j]=count++;
}
//右部
for(i=x;i<n-offset;i++){
result[i][j]=count++;
}
//底部
for(;j>y;j--){
result[i][j]=count++;
}
for(;i>x;i--){
result[i][j]=count++;
}
x++;
y++;
offset++;
loop++;
}
if(n%2!=0){
result[x][y]=count;
}
return result;
}
}
三、区间和
解题思路
建立一个新数组保存每个元素的前缀和,区间和就可以转变为前缀和的差值。具体代码如下:
import java.util.Scanner;
public class Main{
public static void main (String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
//存储输入的值
int[] vec=new int[n];
//存储前缀和
int[] p=new int[n];
//存储累加和
int presum=0;
for(int i=0;i<n;i++){
vec[i]=scanner.nextInt();
presum+=vec[i];
p[i]=presum;
}
while(scanner.hasNextInt()){
int a=scanner.nextInt();
int b=scanner.nextInt();
int sum;
if(a==0)
sum=p[b];
else
之所以为p[a-1]是因为区间和中包括了vec[a]的值
sum=p[b]-p[a-1];
System.out.println(sum);
}
scanner.close();
}
}
四、开发商购买土地
解题思路
根据题目要求可得:
(1)提供整数 n,m建立二维整数数组[n][m]。
(2)将该二维数组用一条竖线或一条横线划分为两部分。
(3)得到每一部分的总价值,然后求这两部分价值相减的值。
根据以上条件可以得知,我们需要找到(3)步骤中的最小值。
代码如下:
import java.util.Scanner;
public class Main{
public static void main (String[] args) {
/* code */
Scanner scanner=new scanner(System.in);
int n=scanner.nextInt();
int m=scanner.nextInt();
int sum=0;
int[][] vec=new int[n][m];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
vec[i][j]=scanner.nextInt();
sum+=vec[i][j];
}
}
int[] hor=new int[n];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
hor[i]+=vec[i][j];
}
}
int[] ver=new int[m];
for(int j=0;j<m;j++){
for(int i=0;i<n;i++){
ver[j]+=vec[i][j];
}
}
int result=Integer.MAX_VALUE;
int horizontaCut=0;
for(int i=0;i<n;i++){
horizontaCut+=hor[i];
result=Math.min(result,Math.abs(sum-2*horizontaCut));
}
int vercalCut=0;
for(int j=0;j<m;j++){
vercalCut+=ver[j];
result=Math.min(result,Math.abs(sum-2*vercalCut));
}
System.out.println(result);
scanner.close();
}
}
五、今日收获
今天的总体难度有所提升。滑动窗口需要将代码与范例结合理解,螺旋矩阵需要对边界进行严格设置。区间和利用了前缀和相减完成了求值,最后一题则是在区间和的基础上进行拓展。在看到这些题目时,我有思路,但是并不清晰,或者有关于边界条件的设置总是不够严谨,在看了carl哥的文章与视频后,思路清晰,能够跟着carl哥完成代码的编写,但是有些地方还是不能够准确无误的写下来,因此还需要多学多练多理解。
今日 学习+解题+博客共3h30min。