算法小白的进阶之路(力扣6~8)

   💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。



非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
 

前言

本栏目将记录博主暑假从0开始刷力扣的算法题,每一条题目我都会把知识点抽丝剥茧地进行分析,以便大家更好的理解和学习,话不多说,肝!

序号标题力扣序号
1找到数组中消失的数字448
2最大连续1的个数485
3提莫攻击495

1.找到数组中消失的数字

题目:

给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

示例 1:

输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]

示例 2:

输入:nums = [1,1]
输出:[2]

解题思路:

对 1−n 的所有数字进行遍历,判断每个数字是否在数组中存在。

第一次遍历,把存在的数都赋值为true,第二次遍历,即选出不存在(false)的数存进数组。

代码(Java)

class Solution {  
    // 定义一个公开的方法,用于找到缺失的数字并返回它们的列表  
    public List<Integer> findDisappearedNumbers(int[] nums) {  
        // 创建一个空的ArrayList来存储结果  
        List<Integer> result = new ArrayList<>();  
  
        // 获取数组的长度  
        int n = nums.length;  
  
        // 创建一个布尔数组,用于记录1到n(包含n)中的每个数字是否出现过  
        // 数组长度为n+1是因为数组索引从0开始,但我们要检查的数字从1开始  
        boolean[] isPresnet = new boolean[n+1];  
  
        // 遍历输入数组中的每个数字  
        for (int num : nums) {  
            // 如果数字在有效范围内(即1到n之间),则标记对应的布尔数组元素为true  
            if (num >= 1 && num <= n) {  
                isPresnet[num] = true;  
            }  
            // 注意:如果num不在这个范围内,我们就不管它,因为题目只关心1到n之间的数字  
        }  
  
        // 再次遍历从1到n的每个数字  
        for (int i = 1; i <= n; i++) {  
            // 如果某个数字在输入数组中未出现过(即对应的布尔数组元素为false)  
            // 则将这个数字添加到结果列表中  
            if(!isPresnet[i]){  
                result.add(i);  
            }  
        }  
  
        // 返回包含所有缺失数字的列表  
        return result;  
    }  
}


2.最大连续1的个数

题目:

给定一个二进制数组 nums , 计算其中最大连续 1 的个数。

示例 :

输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3

解题思路:

遍历数组,设置变量count来记录出现1的次数,设置变量maxCount来记录出现1的最大次数

注意:

遍历数组结束之后,需要再次使用当前的连续 1 的个数更新最大的连续 1 的个数,因为数组的最后一个元素可能是 1,且最长连续 1 的子数组可能出现在数组的末尾,如果遍历数组结束之后不更新最大的连续 1 的个数,则会导致结果错误。

代码(java):

class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
     int maxCount = 0, count = 0;
     int n = nums.length;
     for (int i = 0; i < n; i++) {
        if (nums[i] == 1) {
            count++;
        } else {
            maxCount = Math.max(maxCount,count);
            count = 0;
        }
     }
       maxCount = Math.max(maxCount,count);
     return maxCount;
}
}

3.提莫攻击

题目:

在《英雄联盟》的世界中,有一个叫 “提莫” 的英雄。他的攻击可以让敌方英雄艾希(编者注:寒冰射手)进入中毒状态。

当提莫攻击艾希,艾希的中毒状态正好持续 duration 秒。

正式地讲,提莫在 t 发起攻击意味着艾希在时间区间 [t, t + duration - 1](含 t 和 t + duration - 1)处于中毒状态。如果提莫在中毒影响结束  再次攻击,中毒状态计时器将会 重置 ,在新的攻击之后,中毒影响将会在 duration 秒后结束。

给你一个 非递减 的整数数组 timeSeries ,其中 timeSeries[i] 表示提莫在 timeSeries[i] 秒时对艾希发起攻击,以及一个表示中毒持续时间的整数 duration 。

返回艾希处于中毒状态的  秒数。

示例 1:

输入:timeSeries = [1,4], duration = 2
输出:4
解释:提莫攻击对艾希的影响如下:
- 第 1 秒,提莫攻击艾希并使其立即中毒。中毒状态会维持 2 秒,即第 1 秒和第 2 秒。
- 第 4 秒,提莫再次攻击艾希,艾希中毒状态又持续 2 秒,即第 4 秒和第 5 秒。
艾希在第 1、2、4、5 秒处于中毒状态,所以总中毒秒数是 4 。

示例 2:

输入:timeSeries = [1,2], duration = 2
输出:3
解释:提莫攻击对艾希的影响如下:
- 第 1 秒,提莫攻击艾希并使其立即中毒。中毒状态会维持 2 秒,即第 1 秒和第 2 秒。
- 第 2 秒,提莫再次攻击艾希,并重置中毒计时器,艾希中毒状态需要持续 2 秒,即第 2 秒和第 3 秒。
艾希在第 1、2、3 秒处于中毒状态,所以总中毒秒数是 3 。

解题思路:

  1. 初始化变量
    • ans:用于记录艾希处于中毒状态的总时间(秒)。
    • expired:表示上一次中毒状态应该结束的时间点(秒)。初始化为0,因为没有前一次攻击。
  2. 遍历攻击时间序列
    • 遍历提莫发起攻击的时间序列timeSeries。对于每个时间点timeSeries[i],我们都需要判断这次攻击对艾希中毒状态的影响。
  3. 判断攻击与中毒状态的关系
    • 如果timeSeries[i](当前攻击时间)大于等于expired(上一次中毒结束时间),说明这次攻击是在上一次中毒状态结束后发起的,因此艾希会再次中毒duration秒。我们直接将duration加到ans上。
    • 如果timeSeries[i]小于expired,说明这次攻击是在上一次中毒状态结束前发起的,中毒状态会重新计时。但艾希不会额外增加duration秒的中毒时间,而是从当前攻击时间开始算起,再持续duration秒。因此,我们需要计算从当前攻击时间点到上一次中毒结束时间点之间的时间差(expired - timeSeries[i]),但这部分时间其实会被新的中毒状态所覆盖,所以我们只需要加上从当前攻击时间点到新中毒结束时间的时间(即timeSeries[i] + duration - expired),并加到ans上。
  4. 更新中毒结束时间
    • 无论哪种情况,我们都需要更新expired为当前攻击后duration秒的时间点,即expired = timeSeries[i] + duration

关键点

  • 理解中毒状态的计时和重置机制。
  • 利用expired变量来跟踪上一次中毒状态应该结束的时间点。
  • 通过比较timeSeries[i]expired来判断攻击对中毒状态的影响。
  • 适当地更新ansexpired以反映中毒状态的变化。

class Solution {  
    // 定义一个公开的方法,用于计算艾希处于中毒状态的总秒数  
    public int findPoisonedDuration(int[] timeSeries, int duration) {  
        // 初始化一个变量ans,用于记录艾希处于中毒状态的总秒数  
        int ans = 0;  
        // 初始化一个变量expired,表示上一次中毒状态应该结束的时间点  
        // 初始为0,因为没有前一次攻击时,中毒状态尚未开始  
        int expired = 0;  
          
        // 遍历提莫发起攻击的时间序列  
        for (int i = 0; i < timeSeries.length; ++i) {  
            // 判断当前攻击时间是否大于或等于上一次中毒结束时间  
            // 如果是,说明这次攻击是在上一次中毒结束后发起的  
            if (timeSeries[i] >= expired) {  
                // 直接将中毒持续时间duration加到ans上  
                // 因为这次攻击是在上一次中毒结束后发起的,所以中毒时间不会重叠  
                ans += duration;  
            } else {  
                // 如果当前攻击时间小于上一次中毒结束时间  
                // 说明这次攻击是在上一次中毒状态结束前发起的,中毒状态会重置  
                // 我们需要计算从当前攻击时间点到上一次中毒结束时间之间的差值  
                // 但这部分时间实际上会被新的中毒状态所覆盖,所以我们只需要考虑从当前攻击时间点到新中毒结束时间的时间  
                // 即 timeSeries[i] + duration - expired  
                ans += timeSeries[i] + duration - expired;  
            }  
            // 更新expired为当前攻击后duration秒的时间点  
            // 这是下一次判断中毒状态是否重置的依据  
            expired = timeSeries[i] + duration;  
        }  
        // 遍历完成后,ans中存储的就是艾希处于中毒状态的总秒数  
        // 返回这个值作为答案  
        return ans;  
    }  
}

❤️❤️❤️小郑是普通学生水平,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值