JAVA刷题之数组的总结和思路分享

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱
ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如需转载还请通知˶⍤⃝˶
个人主页:xiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
系列专栏:xiaoxie的刷题系列专栏——CSDN博客●'ᴗ'σσணღ*
我的目标:"团团等我💪( ◡̀_◡́ ҂)" 

( ⸝⸝⸝›ᴥ‹⸝⸝⸝ )欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​+关注(互三必回)! 

beb57f2cc888447ab7e8bbdd4bb1bc08.png

数组篇 

1. 在排序数组中查找元素的第一个和最后一个位置

力扣链接

d1c87083f7bd4365a26e4484ba53a714.png

 我相信大家一看到这题是有序的数组,有点基础的同学们都会想到二分查找法,这一题有思路很容易,但提交时却老是无法通过,这就是因为没有考虑好边界问题了,现在博主为大家介绍两种二分查找法

1.普通二分查找法

做好这一题的关键就在于找到边界

题就是查找 target 在 nums 中的区间,即查找 target 在 nums 中的左右边界。

仔细想的话,要找 target 在 nums 数组中的左右边界,无非存在 3 种情况:

target 在 nums[0] ~ nums[n-1] 中,nums 中存在 target。例如 nums = [5,7,7,8,8,10],target = 8,返回 [3,4]。
target 在 nums[0] ~ nums[n-1] 中,nums 中不存在 target。例如 nums = [5,7,7,8,8,10],target = 6,返回 [-1,-1]。
target < nums[0] 或者 target > nums[n-1]。例如 nums = [5,7,7,8,8,10], target = 4,返回 [-1,-1]。

用两个二分查找,一个二分查找查找左边界,另一个查找右边界,分情况讨论上述的 3 种情况。


class Solution {
    public int[] searchRange(int[] nums, int target) {
        int start = lowerBound(nums, target);
        if (start == nums.length || nums[start] != target)
            return new int[]{-1, -1};
        // 如果 start 存在,那么 end 必定存在
        int end = lowerBound(nums, target + 1) - 1;
        return new int[]{start, end};
    }

    private int lowerBound(int[] nums, int target) {
        int left = 0, right = nums.length - 1; // 闭区间 [left, right]
        while (left <= right) { // 区间不为空
            int mid = left + (right - left) / 2;
            if (nums[mid] < target)
                left = mid + 1; // 范围缩小到 [mid+1, right]
            else
                right = mid - 1; // 范围缩小到 [left, mid-1]
        }
        return left; // right+1
    }

2.红蓝二分查找法

相信大家一直对二分查找法的边界问题一直有困扰,一般来说二分查找就这些东西,在边界和细节上搞人,只要每次做题小心点,就没啥问题。现在博主就为大家介绍另外一种二分查找方法,它不需要考虑那么多问题,只要在最后返回值时多多注意就好了

class Solution {
    public int searchRangeLeft(int[] nums, int target) {
        int left = -1;
        int right = nums.length;
        while (left + 1 != right) {
            int mid = (left + right) / 2;
            if (nums[mid] <= target) {
                left = mid;
            } else {
                right = mid;
            }
        }
        return left;
    }
    
    public int searchRangeRight(int[] nums, int target) {
        int left = -1;
        int right = nums.length;
        while (left + 1 != right) {
            int mid = (left + right) / 2;
            if (nums[mid] < target) {
                left = mid;
            } else {
                right = mid;
            }
        }
        return right;
    }
    public int[] searchRange(int[] nums, int target) {
        int leftIndex = searchRangeLeft(nums, target);
        int rightIndex = searchRangeRight(nums, target);
        if (leftIndex >= rightIndex && leftIndex < nums.length && nums[leftIndex] == target && nums[rightIndex] == target) {
            return new int[] {rightIndex, leftIndex};
        }
        return new int[] {-1, -1};
    }
}

开始时,L指针和 R指针取在搜索区间界外,L=首个元素下标−1,R=末尾元素下标+1,此时所有元素均未着色;
循环条件始终为 L+1 < R,当 L=R 时跳出循环,此时蓝红区域划分完成,所有元素均已着色;
M指针取值始终为 M =(L+R)/2
L指针和 R指针变化的时候直接变为 M指针,即对 M 指针所指向元素进行染色,无需 +1 或者−1;
本模板唯一变化的地方是判断目标元素最终落在左边蓝色区域还是右边红色区域。以不变应万变,根据情况的不同,变换判断条件,大大的降低了出错的可能。

bd82c988822748eb88c81136a103413c.png

98fe462e031541f68718b4eb0b29a65f.png

 这样就找到左下标和右下标啦,再因为该题是找不到就返回-1,所以还要再判断,同时红蓝二分查找法并不只是适用于这题哦,它在大部分的题目都适用,目前博主还没有遇到不适用的情况,所以大家可以放心用,在变换判断条件时和普通二分查找法,大大的降低了出错的可能。

2. 删除有序数组中的重复项---快慢指针

d069c12c176c4d1c9b7d7e3a4d3fb6a3.png

这是力扣上的一道简单题,有的同学可能说了,多余的元素,删掉不就得了。

要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖,所以从中我们第一时间想到也是最简单的就是暴力解法

1.暴力解法

这个题目暴力的解法就是两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组。

public int removeDuplicates(int[] nums) {
    if (nums.length == 0) {
        return 0;
    }
    int k = 1; // 记录唯一元素的个数
    for (int i = 1; i < nums.length; i++) {
        boolean isDuplicate = false;
        // 检查当前元素是否已经存在于前面的唯一元素中
        for (int j = 0; j < k; j++) {
            if (nums[i] == nums[j]) {
                isDuplicate = true;
                break;
            }
        }
        // 如果当前元素是新的唯一元素,则加入到唯一元素列表中
        if (!isDuplicate) {
            nums[k] = nums[i];
            k++;
        }
    }
    return k;
}

 很明显暴力解法的时间复杂度是O(n^2),这道题目暴力解法在leetcode上是可以过的。但这面试中你写这个解法,显然是不能让面试官满意的。博主这有一个使用双指针,快慢指针的解法

2.快慢指针

双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

定义快慢指针

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置

很多同学这道题目做的很懵,就是不理解 快慢指针究竟都是什么含义,所以一定要明确含义,后面的思路就更容易理解了。要解这题的思路如下

首先我们写记录下数组第一个元素的数值:

 int val = nums[0];

然后我们在定义一个快指针和慢指针,指向数组第二个元素:然后快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组;慢指针:指向更新 新数组下标的位置,如下图:

025a42c81a934713a2391590433fd070.png

public int removeDuplicates(int[] nums) {
    int val = nums[0]; // 记录当前唯一元素的值
    int slow = 1; // 慢指针,指向下一个唯一元素应该存放的位置
    for (int fast = 1; fast < nums.length; fast++) {
        if (nums[fast] != val) { // 如果当前元素与前一个唯一元素不相同
            nums[slow] = nums[fast]; // 将当前元素存放到慢指针指向的位置
            val = nums[slow]; // 更新当前唯一元素的值
            slow++; // 慢指针向后移动
        }
    }
    return slow; // 返回唯一元素的个数
}

双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法,写成这样你的代码才可以说达到了面试的高度了,所以我们遇到这一类的题型可以多往快慢指针法那边靠靠,我相信你多练习,多学习,一定可以做到更好。

3.长度最小的子数组

6f80fdd3692b4c0c87c4b07783195d1b.png

 这是力扣上的一道中等难度的数组题,还是一样看到这一题,第一个想到的方法就是用两个for 循环的暴力解法

1.暴力解法

public class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int result = Integer.MAX_VALUE; // 最终的结果
        int sum = 0; // 子序列的数值之和
        int subLength = 0; // 子序列的长度
        for (int i = 0; i < nums.length; i++) { // 设置子序列起点为i
            sum = 0;
            for (int j = i; j < nums.length; j++) { // 设置子序列终止位置为j
                sum += nums[j];
                if (sum >= s) { // 一旦发现子序列和超过了s,更新result
                    subLength = j - i + 1; // 取子序列的长度
                    result = result < subLength ? result : subLength;
                    break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
                }
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == Integer.MAX_VALUE ? 0 : result;
    }
}

2.滑动窗口

该如何把两个for循环变成一个呢,我想大家想到的一定是双指针,对没错,使用双指针,现在博主来为大家介绍一种双指针方法,滑动窗口。所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。它一样是使用双指针,只不过这种解法更像是一个窗口的移动,所以就称为滑动窗口。

在本题中实现滑动窗口,主要确定如下三点:

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?

窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。

窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

解题的关键在于 窗口的起始位置如何移动,如图所示:

760367123a294e95b5d6ff8488933fa3.png

代码如下:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int result = Integer.MAX_VALUE;
        int star = 0,end = 0;
         int sum = 0;
        for(;end < nums.length; end++) {
            sum += nums[end];
            while(sum >= target) {
                int subl = end - star+1;
                result = Math.min(subl,result);//动态更新数值
                sum -= nums[star++];
            } 
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }
}

好了这就是数组篇的全部内容了,后续博主还会持续更新,链表篇等等内容,大家可以点个关注,不错过后续精彩内容。感谢您的阅读,祝您一天生活愉快 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Amazon Code Whisperer 的正式使用,全新 AI 代码工具等你发现!(内附详细安装步骤图解)

文章作者&#xff1a;稚始稚终 关于 Code Whisperer Code Whisperer&#xff0c;亚马逊推出的实时 AI 编程助手&#xff0c;是一项基于机器学习的服务&#xff0c;它可以分析开发者在集成开发环境&#xff08;IDE&#xff09;中的注释和代码&#xff0c;并根据其内容生成多种代…

【LeetCode:2646. 最小化旅行的价格总和 | DFS + DP】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【开发问题解决方法记录】04.dian 权限表单优化

权限表单优化方向&#xff1a; 父级权限从晶点权限表获取做成列表下拉选中 权限名称和编码一行两列 页面id从 select * from APEX_APPLICATION_PAGES where APPLICATION_ID304; 中获取 【遇到的问题1】 DG可以获取到页面信息&#xff0c;但是表和应用程序无法获取到 【问…

机器学习-逻辑回归

一、引言 逻辑回归&#xff08;Logistic Regression&#xff09;是一种广泛应用于分类问题的监督学习算法。尽管名字中含有“回归”二字&#xff0c;但这并不意味着它用于解决回归问题。相反&#xff0c;逻辑回归专注于解决二元或多元分类问题&#xff0c;如邮件是垃圾邮件还是…

TSMaster添加注释

当我们在回放报文的时候&#xff0c;会遇到一些需要添加注释&#xff0c;有以下几种办法进行注释 报文运行时手动注释 在图形窗口回放报文&#xff0c;正在抓取报文或者进行报文回放。工具栏选择添加实时注释&#xff0c;这种办法需要手速快&#xff0c;而且时间对的不是很准…

App内存优化

一、内存优化介绍 1.背景介绍 内存是大问题但缺乏关注压实骆驼的最后一个稻草&#xff08;堆栈溢出&#xff09; 2.内存问题 内存抖动&#xff1a;锯齿状、GC导致卡顿内存泄露&#xff1a;可用内存减少、频繁GC内存溢出&#xff1a;OOM&#xff0c;程序异常 二、优化工具选…

jvs智能bi新增:数据集添加sql自定义节点、添加websocket任务进度动态展示等等

智能bi更新功能 新增: 1.数据集添加sql自定义输入节点&#xff0c;支持mysql Oracle数据源&#xff1b; 用户可以从这些数据源中获取数据&#xff0c;并通过SQL语句对数据进行自定义处理和分析。可以帮助用户更加灵活地处理和分析数据&#xff0c;满足各种个性化的需求。 2.…

识别低效io引起的free buffer waits

产生事发时间段的awr报告 Top 5 wait events 这里重点关注&#xff1a; 1.free buffer waits 2.enq_HW-contention 3.enq:tx-row lock contention enq:HW-contention属于水位线的争用&#xff0c;已经透过alter table allocate extent&#xff0c;提前分配空间,这里不做讨论 …

spring boot+sharding jdbc实现读写分离

shigen日更文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 在shigen之前的文章中&#xff0c;写到了Springboot mybatis plus实现读写分离&#xff0c;没有sharding-jdbc的…

怎么修改按SHIFT键关闭Caps Lock功能?

win11 Step 1> 设置-> 时间和语言Step 2> 输入Step 3> 高级键盘设置Step 4> 语言栏选项 -> 高级设置-> 按CAPS LOCK键 Step 1> 设置-> 时间和语言 Step 2> 输入 Step 3> 高级键盘设置 Step 4> 语言栏选项 -> 高级设置-> 按CAPS LOCK…

同调群的维度 和 同调群的秩

同调群的维度是指同调群中非零元素的最小阶数。与线性代数中对向量空间的维度的理解类似。对同调群&#xff0c;k维同调群的维度是k。 同调群的秩是指同调群中的自由部分的维度。同调群通常包含自由部分和挠部分。同调群的秩是指同调群中自由部分的维度。对同调群&#xff0c;…

python+django教师下乡支教岗位分配管理系统pycharm毕业设计项目推荐

本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中&#xff0c;方便对数据进行操作本课题基于WEB的开发平台 1.运行环境&#xff1a;python3.7/python3.8。 2.IDE环境&#xff1a;pycharmmysql5.7; …

多线程(初阶八:计时器Timer)

目录 一、标准库中的计时器 1、计时器的概念 2、计时器的简单介绍 二、模拟实现一个计时器 1、思路 &#xff08;1&#xff09;计数器中要存放任务的数据结构 &#xff08;2&#xff09;存放优先级队列中的类型&#xff1a;自定义任务类MyTimerTask &#xff08;3&…

用python找到音乐数据的位置,并实现音乐下载

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 需求分析: 有什么需求要实现? 这些需求可以用什么技术实现? 找到音乐数据的位置, 分析 不同音乐的链接有何规律?https://lx-sycdn.kuwo.cn/b784688662c82db8…

RocketMq环境搭建

目录 MQ作用 RocketMQ背景 MQ对比 RocketMQ环境搭建 搭建dashboard可视化界面 MQ作用 异步解耦削峰 RocketMQ背景 ​ RocketMQ是阿里巴巴开源的一个消息中间件&#xff0c;在阿里内部历经了双十一等很多高并发场景的考验&#xff0c;能够处理亿万级别的消息。2016年开源…

Win10无法删除文件需要管理员权限的解决方法

在Win10电脑中&#xff0c;用户想要删除不需要的文件&#xff0c;却收到了需要管理员权限才能删除&#xff0c;导致用户自己无法将文件删除掉。下面小编给大家带来Win10系统删除文件需要权限的解决方法&#xff0c;解决后用户在Win10电脑上就能删除任意文件了。 Win10无法删除文…

TCP协议实现一对一聊天

服务端代码&#xff1a; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner;/*** 发送消息线程*/ class Send e…

香港优才计划申请获批后,才发现原来香港年薪100w并不难!

香港优才计划申请获批后&#xff0c;才发现原来香港年薪100w并不难&#xff01; 在香港工作的话&#xff0c;给我个人的感觉就是工作和生活是分开的&#xff0c;无论是同事还是上司。比如员工在休假的时候从来不会突然来个电话让你忙个工作或者加个班&#xff0c;也不会八卦你的…

Python 日志(略讲)

日志操作 日志输出&#xff1a; # 输出日志信息 logging.debug("调试级别日志") logging.info("信息级别日志") logging.warning("警告级别日志") logging.error("错误级别日志") logging.critical("严重级别日志")级别设置…

MySQL授权密码

mysql> crate databases school charcter set utf8; Query OK, 1 row affected, 1 warning (0.00 sec) 2.在school数据库中创建Student和Score表 mysql> use school Database changed mysql> create table student-> -> (id int(10) primary key auto_incremen…