当前位置: 首页 > web >正文

LeetCode-数组技巧题目

数组题目技巧总结


二分查找

确保区间不变量,保持左闭右闭

如果middle的值已经比target小了,那么这个middle值一定不等于target,也就是target一定在middle的右面,所以left=middle+1

        while(left<=right){//防止出现两个很大的数字相加之后溢出int middle=(right-left)/2+left;if(nums[middle]<target){left=middle+1;}else if(nums[middle]>target){right=middle-1;}else{return middle;}}

移除元素

使用好快慢指针,fast指针寻找需要放在新数组的元素,slow指针对应这个元素在新数组的下标

        int slow=0;for(int fast=0;fast<nums.length;fast++){//如果当前fast指向的数组元素不等于VAL,那么就要放在slow下表对应的新数组位置中if(nums[fast]!=val){nums[slow++]=nums[fast];}}

滑动窗口

遍历一遍终点指针,在这过程中更新初始指标,按照最小或者最大去更新滑动窗口的长度,主要注意left指针怎么移动,以及怎么判断这一次的初始指针移动结束

class Solution {public int minSubArrayLen(int target, 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>=target){//更新遍历初始指针条件,更新滑动窗口长度result=Math.min(result,right-left+1);sum-=nums[left++];}}return result==Integer.MAX_VALUE ? 0 : result;}
}

模拟行为

把握住循环不变量,遇见螺旋矩阵,对于四边的遍历操作一定要统一规则

class Solution {public int[][] generateMatrix(int n) {//确定四边边界值,往中间逼近int[][] result=new int[n][n];int top=0;int right=n-1;int bottom=n-1;int left=0;int count=1;while(count<=n*n){int a=left;while(count<=n*n && a<right){result[top][a++]=count;count++;}int b=top;while(count<=n*n && b<bottom){result[b++][right]=count;count++;}int c=right;while(count<=n*n && c>left){result[bottom][c--]=count;count++;}            int d=bottom;while(count<=n*n && d>top){result[d--][left]=count;count++;}if(top==bottom && left==right){result[top][left]=count;count++;}top++;bottom--;left++;right--;}return result;}
}

 螺旋的三道题都可以用四个边界指针进行逼近。

前缀和

下面的两道题目,计算区间,区间差值,很好用,数组的内容就这些了,继续努力。

977.有序数组的平方(左右双指针)


给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

    示例 1:

    输入:nums = [-4,-1,0,3,10]
    输出:[0,1,9,16,100]
    解释:平方后,数组变为 [16,1,0,9,100]
    排序后,数组变为 [0,1,9,16,100]

    示例 2:

    输入:nums = [-7,-3,2,3,11]
    输出:[4,9,9,49,121]提示:
    • 1 <= nums.length <= 104
    • -104 <= nums[i] <= 104
    • nums 已按 非递减顺序 排序
    class Solution {public int[] sortedSquares(int[] nums) {//新建一个数组,双指针每次扫描一个最大的元素放进这个数组里面int n=nums.length;int[] result=new int[n];//定义数组的长度l=n-1int k=n-1;//最终要放满数组int left=0;int right=k;while(k>=0){int ltwo=nums[left]*nums[left];int rtwo=nums[right]*nums[right];if(ltwo<rtwo){result[k--]=rtwo;right--;}else{result[k--]=ltwo;left++;}}return result;}
    }
    • 由于题目中有负数也有正数,最终要用平方进行非递减排序,我们可以想象最左侧和最右侧永远有一个最大的或者两个一样最大的。
    • 有了这个思路我们就可以用双指针left和right向中间逼近,由于没有空间复杂度的要求,我们可以新建一个空数组,将左右两边最大的放入这个空数组中。
    • while循环的终止条件是装满数组,用新数组长度下标大于等于0作为判断条件就可以。
    • 移除元素相关的数组题目思想是快慢双指针,这道题是左右两端向中间逼近的双指针


    区间和(利用数组的前缀和)

    import java.util.Scanner;public class Main
    {public static void main(String[] args){Scanner sc = new Scanner(System.in);//计算区间常用 前缀和int n=sc.nextInt();//保留前缀和建立一个数组int[] pre=new int[n];int presum=0;for(int i=0;i<n;i++){int input=sc.nextInt();presum+=input;pre[i]=presum;}//hasNextInt()是一个 Java 中的 Scanner 类的方法,用于检查输入流中是否还有一个整数。如果输入流中还有一个整数,该方法将返回 true;否则返回 falsewhile(sc.hasNextInt()){int x=sc.nextInt();int y=sc.nextInt();if(x==0){System.out.println(pre[y]);}else{System.out.println(pre[y]-pre[x-1]);}}}
    }
    • 熟悉一下ACM的输入格式,从psvm到sout手敲一遍
    • 假设输入的五行数字为1,2,3,4,5 那么pre[1]和pre[3]就等于3和10,记录当前下标对应的值和之前的值的和,就是pre数组存放的元素。
    • 这道题的案例求1到3的区间和,也就是2+3+4,那么就相当于pre[3]-pre[0],去掉原数组的第一个元素
    • 利用scanner.hasNextInt来获取后面的若干组区间和,如果区间和的左区间x为0,那么直接输出pre[y]就可以,因为pre[0]包含了第一个元素。其余情况输出pre[y]-pre[x-1] 

     


    开发商购买土地(利用数组前缀和)

    import java.util.Scanner;public class Main{public static void main(String[] args){Scanner sc=new Scanner(System.in);int n=sc.nextInt();int m=sc.nextInt();//方便作差,计算总和sum,往最小更新,result设为最大值int sum=0;int result=Integer.MAX_VALUE;int[][] block=new int[n][m];for(int i=0;i<n;i++){for(int j=0;j<m;j++){block[i][j]=sc.nextInt();sum+=block[i][j];}}//横向分的最小值和纵向分的最小值取最小值//横向分int[] prerow=new int[n];for(int i=0;i<n;i++){for(int j=0;j<m;j++){prerow[i]+=block[i][j];}}//纵向分int[] precol=new int[m];for(int i=0;i<m;i++){for(int j=0;j<n;j++){precol[i]+=block[j][i];}}//更新最小值int rowsum=0;for(int i=0;i<n;i++){rowsum+=prerow[i];result=Math.min(result,Math.abs((sum-rowsum)-rowsum));           }//纵向分更新最小值int colsum=0;for(int i=0;i<m;i++){colsum+=precol[i];result=Math.min(result,Math.abs((sum-colsum)-colsum)); }System.out.println(result);}
    }
    • 重点在于更新最小值更新的是什么值,是当前横向分或者纵向分,取的一部分(前缀和)和另一部分的差值最小。前缀和很容易得到,那么差值就是用总和减去当前部分(得到另一部分)再减去当前部分取绝对值abs(得到差值)
    • 理解差值怎么获取了,就声明一个最大变量result,然后在输入n行m列元素的时候计算一下总和sum。
    • 横向和纵向的前缀和分别建立一个一维数组,遍历数组的每一行相加、遍历数组的每一列相加得到
    • 然后就遍历横向划分更新结果,再遍历纵向划分更新结果,最终System.out.println(result)输出结果

    http://www.xdnf.cn/news/9612.html

    相关文章:

  • 影刀RPA-20-高级操作题2
  • 后端思维之高并发处理方案
  • 使用LSTM对销售数据进行预测
  • 简乐 1.4.0 | 非常简洁 无损下载 畅听全网
  • 聊一聊 C# NativeAOT 多平台下的函数导出
  • Milvus向量Search查询综合案例实战(下)
  • Telnet 命令详解
  • 深度学习---注意力机制(Attention Mechanism)
  • docker 网络-用户定义网络
  • 【OCSA 2025】征稿通道已经开启​
  • 【连接器专题】 EIA-364 系列标准的完整列表
  • 加减数值策略
  • 【笔记】修复ImportError: cannot import name ‘Mapping‘ from ‘collections‘
  • DeepSpeed常见面试问题
  • PMO价值重构:从项目管理“交付机器”到“战略推手”
  • 消防应急装备管理:打造消防营区智能仓储
  • 36. 编写异步webdriver接口请求客户端
  • Vector - VT System - 板卡_VT板卡使用介绍_08
  • 【LangGraph】智能体工作流的新基石
  • uniapp小程序开发,判断跳转页面是否需要登录方法封装
  • 网站每天几点更新,更新频率是否影响网站收录
  • 【b站计算机拓荒者】【2025】微信小程序开发教程 - chapter3 项目实践 - 3人脸识别采集统计人脸检测语音识别
  • el-table配置表头固定而且高度变化
  • js-day4
  • 新能源汽车霍尔线束介绍
  • Kubernetes Dashboard 安装部署、访问与管理实战实验
  • 深入浅出Nacos:微服务架构中的服务发现与配置管理利器
  • 软件包管理系统的架构与生态机制
  • 【Pandas】pandas DataFrame between_time
  • Python 字典渲染字符串