算法:数组part02: 209. 长度最小的子数组 + 59.螺旋矩阵II + 代码随想录补充58.区间和 + 44. 开发商购买土地

算法:数组part02: 209. 长度最小的子数组 + 59.螺旋矩阵II+ 代码随想录补充58.区间和 + 44. 开发商购买土地

209. 长度最小的子数组

题目:https://leetcode.cn/problems/minimum-size-subarray-sum/description/
文章讲解:https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html
视频讲解:https://www.bilibili.com/video/BV1tZ4y1q7XE(思想较难,看视频复习)

思想

  • 找出长度最小的子数组,用暴力解法,两层for循环列出所有的可能情况(以i为头以j为尾,这样i从头遍历到尾,找到以数组所以元素为头的子数组)可以解题;
  • 要想用一层for实现上面的效果,就需要用到滑动窗口(双指针)的思想,for循环滑动窗口的右边界,左边界在这层for的逻辑中去修改;就可以达到O(n)的时间复杂度;

解题

暴力解法
//C++版
class Solution {
public:int minSubArrayLen(int s, vector<int>& nums) {int result = INT32_MAX; // 最终的结果int sum = 0; // 子序列的数值之和int subLength = 0; // 子序列的长度for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为isum = 0;for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为jsum += nums[j];if (sum >= s) { // 一旦发现子序列和超过了s,更新resultsubLength = j - i + 1; // 取子序列的长度result = result < subLength ? result : subLength;break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break}}}// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列return result == INT32_MAX ? 0 : result;}
};
正解
class Solution {public int minSubArrayLen(int target, int[] nums) {//利用滑动窗口(左右指针指示滑动窗口两端,本身还是双指针的思想)int left=0;int sum=0;//初始的result需要设为整数的最大值int result=Integer.MAX_VALUE;//记录满足条件的子串长度int sublength=0;for(int right=0;right<nums.length;right++){sum+=nums[right];while(sum>=target){sublength=right-left+1;result=Math.min(sublength,result);sum-=nums[left++];}}return result==Integer.MAX_VALUE?0:result;}
}////这个是参考答案,要更好理解,上面的是我写的
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;}
}

总结

for循环循环的是滑动窗口的右边界,左边界在这个循环逻辑的内部利用while()去改变;感觉这个思想要记下来,第一次接触基本想不出;

59.螺旋矩阵II

题目:https://leetcode.cn/problems/spiral-matrix-ii/description/
文章链接:https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html

思想

文章中总结的思路很好,要坚持循环不变量的原则:搞清区间的边界,以及每次循环的判断条件要一样;
边界确定:每行或每列的末尾不属于本行,而作为下一行的开始
螺旋矩阵的n:n为偶数loop=2/n,n为奇数就需要单独处理最内部的一个位置;

解题

class Solution {public int[][] generateMatrix(int n) {int nums[][]=new int[n][n];//循环圈数int loop=0;int startX=0;int startY=0;int i,j;//用来表示每行最后几个不包含int offset=1;//用来表示填充的数字int count=1;int mid=n/2;while(loop<n/2){//下面的四个for就是模拟转了一圈//首先是左上到右上for(j=startY;j<n-offset;j++){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++;loop++;offset++;}//奇数的情况单独给中间元素赋值if(n%2!=0){nums[mid][mid]=count;}return nums;}
}////这个是参考答案,要更好理解,上面的是我写的
class Solution {public int[][] generateMatrix(int n) {int[][] nums = new int[n][n];int startX = 0, startY = 0;  // 每一圈的起始点int offset = 1;int count = 1;  // 矩阵中需要填写的数字int loop = 1; // 记录当前的圈数int i, j; // j 代表列, i 代表行;while (loop <= n / 2) {// 顶部// 左闭右开,所以判断循环结束时, j 不能等于 n - offsetfor (j = startY; j < n - offset; j++) {nums[startX][j] = count++;}// 右列// 左闭右开,所以判断循环结束时, i 不能等于 n - offsetfor (i = startX; i < n - offset; i++) {nums[i][j] = count++;}// 底部// 左闭右开,所以判断循环结束时, j != startYfor (; j > startY; j--) {nums[i][j] = count++;}// 左列// 左闭右开,所以判断循环结束时, i != startXfor (; i > startX; i--) {nums[i][j] = count++;}startX++;startY++;offset++;loop++;}if (n % 2 == 1) { // n 为奇数时,单独处理矩阵中心的值nums[startX][startY] = count;}return nums;}
}

总结

  • 螺旋矩阵II的关键点在于循环不变量:确定边界,循环条件不变;
  • 时间复杂度为O(n2);

代码随想录补充58.区间和

题目+讲解:https://www.programmercarl.com/kamacoder/0058.%E5%8C%BA%E9%97%B4%E5%92%8C.html

思想

  • 暴力解法:直接遍历相应区间,计算总和的值,时间复杂度为O(m*n);
  • 最优解:空间换时间,用一个新数组,新数组的每个元素存储给出数组前i位元素的和,用到时直接取相应的p[b]-p[a-1]即可;如果a=0,则结果直接为p[b];

解题

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 presum=0;//定义一个新数组,每个位置存前i位元素的和int[] p=new int[n];int sum=0;//为原始数组、新数组每个元素赋值for(int i=0;i<n;i++){vec[i]=scanner.nextInt();presum+=vec[i];p[i]=presum;}//scanner.hashNextInt()用来判断输入是否还有下一个元素:即是否还需要求区间和while(scanner.hashNextInt()){int a=scanner.nextInt();int b=scanner.nextInt();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[] 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();}
}

总结

  • 区间和思想其实很好理解:就是牺牲空间先存储前i位的和,后面做减法就好;

44. 开发商购买土地

思想:

暴力解法即利用三层for循环,第一层分别遍历横向的n-1个分割线和纵向的m-1个分割线,剩下两层for用来求总和;时间复杂度为O(n3)
优化解法:(1)用区间和的思想,先用新数组1存横向前i行元素的总和,再用新数组2存纵向前i行元素的总和;(2)也可以用优化暴力解法来代替三层for;时间复杂度O(n2)

解题

//暴力
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int m = scanner.nextInt();int[][] grid = new int[n][m];// 输入区块权值for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {grid[i][j] = scanner.nextInt();}}int minDiff = Integer.MAX_VALUE;// 1. 枚举所有横向分割线(i 从 0 到 n-2)for (int i = 0; i < n - 1; i++) {int sumA = 0;int sumB = 0;// 计算上半部分(A 区域)的总和for (int x = 0; x <= i; x++) {for (int y = 0; y < m; y++) {sumA += grid[x][y];}}// 计算下半部分(B 区域)的总和for (int x = i + 1; x < n; x++) {for (int y = 0; y < m; y++) {sumB += grid[x][y];}}int diff = Math.abs(sumA - sumB);if (diff < minDiff) {minDiff = diff;}}// 2. 枚举所有纵向分割线(j 从 0 到 m-2)for (int j = 0; j < m - 1; j++) {int sumA = 0;int sumB = 0;// 计算左半部分(A 区域)的总和for (int x = 0; x < n; x++) {for (int y = 0; y <= j; y++) {sumA += grid[x][y];}}// 计算右半部分(B 区域)的总和for (int x = 0; x < n; x++) {for (int y = j + 1; y < m; y++) {sumB += grid[x][y];}}int diff = Math.abs(sumA - sumB);if (diff < minDiff) {minDiff = diff;}}System.out.println(minDiff);}
}//区间和思想
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[m];for (int j = 0; j < m; j++) {for (int i = 0; i < n; 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));// 更新result。其中,horizontalCut表示前i行的和,sum - horizontalCut表示剩下的和,作差、取绝对值,得到题目需要的“A和B各自的子区域内的土地总价值之差”。下同。}int verticalCut = 0;for (int j = 0; j < m; j++) {verticalCut += vertical[j];result = Math.min(result, Math.abs((sum - verticalCut) - verticalCut));}System.out.println(result);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 result = Integer.MAX_VALUE;int count = 0; // 统计遍历过的行// 行切分for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {count += vec[i][j];// 遍历到行末尾时候开始统计if (j == m - 1) {result = Math.min(result, Math.abs(sum - 2 * count));}}}count = 0;// 列切分for (int j = 0; j < m; j++) {for (int i = 0; i < n; i++) {count += vec[i][j];// 遍历到列末尾时候开始统计if (i == n - 1) {result = Math.min(result, Math.abs(sum - 2 * count));}}}System.out.println(result);scanner.close();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/90669.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/90669.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring 核心知识点梳理 1

目录 Spring Spring是什么&#xff1f; Spring中重要的模块 Spring中最重要的就是IOC(控制反转)和AOP(面向切面编程) 什么是IOC DI和IOC之间的区别 为什么要使用IOC呢&#xff1f; IOC的实现机制 什么是AOP Aop的核心概念 AOP的环绕方式 AOP发生的时期 AOP和OOP的…

Kafka运维实战 07 - kafka 三节点集群部署(混合模式)(KRaft 版本3.7.0)

目录环境准备主机准备补充说明JDK安装 (三台主机分别执行)下载jdkjdk安装kafka 部署(三台主机分别执行)kafka 下载kafka 版本号结构解析kafka 安装下载和解压安装包(3台主机都执行)配置 server.properties &#xff08;KRaft 模式&#xff09;192.168.37.10192.168.37.11192.16…

linux内核与GNU之间的联系和区别

要理解操作系统&#xff08;如 GNU/Linux&#xff09;的组成&#xff0c;需要明确 内核&#xff08;Kernel&#xff09; 和 GNU 工具链 各自的功能&#xff0c;以及它们如何协作构成完整的操作系统。以下是详细分析&#xff1a;1. 内核&#xff08;Kernel&#xff09;的功能 内…

文件包含学习总结

目录 漏洞简介 漏洞原理 漏洞分类 漏洞防御 漏洞简介 程序开发人员一般会把重复使用的函数写到单个文件中&#xff0c;需要使用某个函数时直接调用此文件&#xff0c;而无需再次编写&#xff0c;这种文件调用的过程一般被称为文件包含。程序开发人员一般希望代码更灵活&…

TQZC706开发板教程:创建PCIE项目

本例程基于zc706开发板&#xff0c;使用xdma核创建PCIE项目&#xff0c;最终实现插入主机可识别出Xilinx设备。在vivado中创建一个空的706项目。创建完成后添加IP核-->搜索xdma-->双击打开配置。添加XDMA核如下所示basic配置peic id中设置设备号等信息&#xff0c;这里保…

科技赋能景区生.态,负氧离子气象监测站筑牢清新防线

负氧离子气象监测站&#xff0c;如同景区空气质量的坚固防线&#xff0c;默默守护着每一寸土地的清新。​它以精准的监测能力为防线基石。借助 “吸入式电容收集法”&#xff0c;能敏锐捕捉空气中负氧离子的踪迹&#xff0c;精准测量其浓度&#xff0c;同时将温度、湿度、PM2.5…

AMD官网下载失败,不让账户登录下载

别使用163邮箱 使用QQ邮箱&#xff0c;然后用GPT生成一个外国&#xff0c;比如日本的地区信息填上去就可以下载了

Elasticsearch-8.17.0 centos7安装

下载链接 https://www.elastic.co/downloads/past-releases/elasticsearch-8-17-0 https://www.elastic.co/downloads/past-releases/logstash-8-17-0 https://www.elastic.co/cn/downloads/past-releases/kibana-8-17-0https://artifacts.elastic.co/downloads/elasticsearch/…

windows下SAS9.4软件下载与安装教程

SAS 9.4是SAS公司推出的一款功能强大的统计分析软件&#xff0c;广泛应用于数据分析、商业智能、预测分析、数据挖掘及统计建模等多个领域。数据处理与管理能力&#xff1a;SAS 9.4支持多种数据格式的导入导出&#xff0c;包括JSON、XML等&#xff0c;便于处理来自Web和API的数…

MyBatis-Plus极速开发指南

MyBatis-Plus简介MyBatis-Plus 是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;简化开发&#xff0c;提高效率。它提供了以下主要特性&#xff1a;无侵入&#xff1a;只做增强不做改变&#xff0c;引入它不会对现有工程产生影响强大的 …

Django接口自动化平台实现(五)

8. 测试用例执行 预期效果如下&#xff1a;用例执行逻辑如下&#xff1a;前端提交用例 id 列表到后台&#xff0c;后台获取每一条用例的信息&#xff1b;后台获取域名信息、用例 id 列表&#xff1b;对用例的请求数据进行变量的参数化、函数化等预处理操作&#xff1b;根据先后…

一个没有手动加分号引发的bug

最近因为分号的疏忽&#xff0c;导致出现了一个bug&#xff0c;记录下来&#xff0c;分享给大家。 1、一个示例 给你下面这一段代码&#xff0c;你根据经验判断一下运营结果 let [a,b] [a,b] let [x,y] [1,2] if(x < y){[x,y] [y,x][a,b] [b,a] }按照一般的理解&#xf…

Elasticsearch安全审计日志设置与最佳实践

一、Elasticsearch安全审计简介 审计日志&#xff08;Audit Logging&#xff09;用于记录Elasticsearch中的安全相关事件&#xff0c;包括认证失败、连接拒绝、数据访问事件以及通过API对安全配置&#xff08;如用户、角色、API密钥&#xff09;的变更记录。 注意&#xff1a;审…

算法训练营day29 贪心算法③ 134. 加油站、135. 分发糖果 、860.柠檬水找零、406.根据身高重建队列

贪心算法的第三篇博客&#xff0c;继续脑筋风暴&#xff01; 134. 加油站 写在前面 这道题规定了有解的话&#xff0c;必定为唯一解 贪心思路 直接从全局进行贪心选择&#xff0c;情况如下&#xff1a; 情况一&#xff1a;如果gas的总和小于cost总和&#xff0c;那么无论从…

【09】C#入门到精通——C# 结构体对齐 与 常用数据 对应关系

文章目录1 C# 结构体对齐1.1 默认对齐方式1.2 节对齐方式设置1.3 偏移量设置2 C#与C/C之间类型的对应关系1 C# 结构体对齐 1.1 默认对齐方式 struct默认对齐方式&#xff0c;结构体长度必须是&#xff0c;最大成员长度的整数倍&#xff0c;所以下面结构体大小是 24 (实际占用…

pytest 测试报告生成方案有哪些?

在 pytest 中&#xff0c;除了 Allure 和 HTMLTestRunner&#xff0c;还有许多其他生成测试报告的方法和插件。以下是一些常用的方案及其特点&#xff1a;1. pytest-html&#xff08;官方推荐&#xff09;特点&#xff1a;轻量级、易集成&#xff0c;生成独立的 HTML 报告。安装…

Unity中EditorPrefs与PlayerPrefs对比分析

Unity中EditorPrefs与PlayerPrefs对比分析 EditorPrefs与PlayerPrefs是Unity引擎中用于数据持久化的两个核心类&#xff0c;分别用于于编辑器扩展与游戏运行时场景。以下从设计目标、存储位置、数据类型、生命周期、安全性、使用场景等方面展开对比&#xff0c;并结合代码示例说…

蓝光中的愧疚

蓝光中的愧疚活动结束那晚&#xff0c;深圳的空气吸饱了水汽&#xff0c;沉甸甸地压在胸口。我站在西乡社区活动中心冰凉的玻璃门外&#xff0c;目送着最后一个离开的王老师。她关掉门厅的灯&#xff0c;电子门锁合拢时发出轻微却尖锐的“嘀”声&#xff0c;像一根细针扎在我紧…

Linux: network: wireshark: esp attempt to detec null-encrypted esp payloads

最近看到一个pcap文件&#xff0c;里面有esp协议包&#xff0c;而且是明文/没有加密的消息&#xff0c;为什么wireshark没有将esp上层的tcp/sip消息没有解出来。 类似于Info列只有ESP的信息。后来选中了协议选项里的&#xff1a;attempt to detect/decode NULL encrypted ESP p…

10分钟搭建脚手架:Spring Boot 3.2 + Vue3 前后端分离模板

10分钟搭建脚手架&#xff1a;Spring Boot 3.2 Vue3 前后端分离模板一、项目结构设计二、后端搭建&#xff08;Spring Boot 3.2&#xff09;1. 快速初始化&#xff08;使用 Spring Initializr&#xff09;2. 核心配置application.yml跨域配置 CorsConfig.java3. 安全配置Secur…