LeetCode算法刷题|第二天| 209.长度最小的子数组、 59.螺旋矩阵II、区间和、开发商购买土地

209.长度最小的子数组

题目链接:点击跳转-题目链接
文章讲解:点击跳转-文字讲解
视频讲解:点击跳转-视频讲解

思路:穷举数组中所有的子数组,然后求和与目标值比较
方法:暴力、滑动窗口

代码实现:

//1、定义初始变量
int left = 0; //起始位置
int sum = 0; //滑动窗口内的元素和
int result = Integer.MAX_VALUE; //满足条件数组的最小长度
//2、循环遍历数组,获得满足条件的最小数组
for (int right = 0; right < nums.length; right++) {
	sum += nums[right]; //窗口内元素的和
	//窗口内的和满足目标值
	if (sum >= target){
		//1、获取 最小数组长度
		result = Math.min(result,right-left+1);
		//2、窗口内的和 改变
		sum -= nums[left];
		//3、起始位置 改变
		left++;
	}
}
//3、返回数据
return result == Integer.MAX_VALUE ? 0 : result;
Tips:
     暴力求解需要两层for循环,时间复杂度O();
     滑动窗口使用一个for循环比遍历所有的元素,区间开始位置的指针不再使用循环来表示,
     时间复杂度为O(n).

59.螺旋矩阵II

题目链接:点击跳转-题目链接
文章讲解:点击跳转-文字讲解
视频讲解:点击跳转-视频讲解

思路:模拟顺时针画矩阵的过程:填充数据时:上边从左到右,右边从上到下,下边从右到左,左边从下到上。

//1、初始化变量
int[][] nums = new int[n][n]; //输出的数组
int startX = 0, startY = 0; // 每一圈的起始点
int offset = 1; //偏移量
int count = 1; //填充的数字
int loop = 1; //记录当前圈数
int i, j; //i代表行,j代表列

//2、转圈
while (loop <= n / 2) {
    //上边:从原点开始,列j改变.遵循左闭右开原则,列不对第一行的最后一个位置元素值操作 j=n-offset
    for (j = startY; j < n - offset; j++) {
        nums[startX][j] = count;
        count++;
    }
    //右边:行i改变,列j值不变(j=n-offset).遵循左闭右开原则,行不对右边最后一个元素操作 i= n-offset
    for (i = startX; i < n - offset; i++) {
        nums[i][j] = count;
        count++;
    }
    //下边:列j改变(j=n-offset),行i不变(i= n-offset).遵循左闭右开原则,列不对左边最后一个元素操作
    for (; j > startY; j--) {
        nums[i][j] = count;
        count++;
    }
    //左边:列j不变(j=startY),行i改变((i= n-offset)). 遵循左闭右开原则,行不对左边最后一个元素操作
    for (; i > startX; i--) {
        nums[i][j] = count;
        count++;
    }
    startX++;
    startY++;
    offset++;
    loop++;
}
//3、n 为奇数时,单独处理矩阵中心的值
if (n % 2 == 1) {
    nums[startX][startY] = count;
}
//4、返回数据
return nums;
Tips:
    边界条件一定要一致,这里使用左闭右开,
	在进行数据填充时,区间右边的数据由下家处理,按顺时针方向最终完成数据填充。

区间和(模拟笔试)

题目链接:点击跳转-题目链接

思路:用到数组常用的解题技巧–前缀和前缀和的思想是重复利用计算过的子数组之和,从而降低区间查询需要累加计算的次数。

import java.util.Scanner;

public class Main{
    public static void main(String[] arges){
        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{ //使用区建尾减去区间头的前一个数值
                sum = p[b]-p[a-1];
            }
           System.out.println(sum);
        }
        //关闭工作流
       scanner.close();
    }    
}

开发商购买土地

题目链接点击跳转-题目链接

思路:使用前缀和的思想求解,将矩阵中行和列的和求出来,方便的知道划分两个区间的和是多少。

import java.util.Scanner;

//定义主类和主方法
public class Main {
    public static void main(String[] args) {
        
        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[] horizontal = new int[n];
        for(int i = 0;i<n;i++){
            for(int j = 0;j<m;j++){
                horizontal[i] += vec[i][j];
            }
        }
        
        //统计纵向
        int[] vertical  = new int[n];
        for(int j = 0;j<n;j++){
            for(int i = 0;i<m;i++){
                vertical [j] += vec[i][j];
            }
        }
        
        int result = Integer.MAX_VALUE;
        int horizontalCut = 0;
        //横向切割
        for(int i = 0;i<n;i++){
            horizontalCut += horizontal[i];
            result = Math.min(result, Math.abs((sum-horizontalCut)-horizontalCut));
            //上行代码中的 (sum-horizontalCut)-horizontalCut 等同于 sum - 2 * horizontalCut
        }
        //纵向切割
        int verticalCut = 0;
        for (int j = 0; j < m; j++) {
            verticalCut += vertical[j];
            result = Math.min(result, Math.abs(sum - 2 * verticalCut));
        }
        //输出横向和竖向切割两种方式中切割后,矩阵两部分的最小值差值
        System.out.println(result);
        scanner.close();
    }}
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值