LeetCode算法日记 - Day 5: 长度最小的子数组、无重复字符的最长子串

目录

[1. 长度最小的子数组](#1. 长度最小的子数组)

[1.1 题目解析](#1.1 题目解析)

[1.2 解法](#1.2 解法)

[1.3 代码实现](#1.3 代码实现)

[2. 无重复字符的最长子串](#2. 无重复字符的最长子串)

[2.1 题目解析](#2.1 题目解析)

[2.2 解法](#2.2 解法)

[2.3 代码实现](#2.3 代码实现)


1. 长度最小的子数组

209. 长度最小的子数组 - 力扣(LeetCode)

给定一个含有 n个正整数的数组和一个正整数 target

找出该数组中满足其总和大于等于target的长度最小的 子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度**。** 如果不存在符合条件的子数组,返回 0

示例 1:

复制代码
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

复制代码
输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

复制代码
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

1.1 题目解析

针对一段连续区间,寻找最小长度的子数组,使其元素和大于等于给定目标值(通常称为"最小子数组和"问题),利用 正数相加和只能增加的**单调性,**使用滑动窗口方法解决。此利用单调性避免没有必要的枚举行为。虽然有两层循环,但是时间复杂度为O(N)。

1.2 解法

滑动窗口的核心是使用两个指针(左指针和右指针)动态调整窗口范围:

  • 窗口定义:窗口代表子数组,其和记为 sum。
  • 目标:找到最小长度 {min_len}
  • 关键思想
    • 移动 right 扩大窗口,增加 sum,直到 sum>=target。
    • 然后移动 缩小窗口,减少 sum,同时检查是否仍满足 sum>=target (因为移除小元素可能保留满足条件的更小子数组)。
    • 更新 min_len 为当前窗口长度 right-left+1 的最小值。
  • 为什么高效:每个元素最多被添加和移除一次,确保线性时间复杂度

以下是滑动窗口算法的具体步骤

i)初始化指针:左右指针定义从0下标开始

ii)移动右指针:将 right 位置的元素加入窗口,直到 sum>=target

iii)缩小窗口并检查:将 left 位置的元素移动出窗口,并且检查是否 sum>= target

iiii)循环 ii, iii 直到 right>=n

1.3 代码实现

java 复制代码
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int min_len=Integer.MAX_VALUE,n=nums.length,sum =0;
        for(int left =0,right=0;right<n;right++){
            sum += nums[right];
            while(sum >= target){
                int length = right-left+1;
                min_len = Math.min(min_len,length);
                sum-=nums[left++];
            }
        }
        return min_len == Integer.MAX_VALUE ?0:min_len;
    }
}

2. 无重复字符的最长子串

3. 无重复字符的最长子串 - 力扣(LeetCode)

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。

示例 1:

复制代码
输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

复制代码
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

复制代码
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串

2.1 题目解析

本题目可以使用滑动窗口来解决,当窗口里未包含字符时增大窗口,并且记录新的最长子字符串值,当遇到已经包含的字符时,通过 while 循环直接跳过重复的元素。

i)可以看得出当窗口没有重复元素删除时,字符串长度始终是不会增加的。

ii)我们可以直接通过 while 循环快速移动并且删除重复的元素。

iii)while 循环之后再记录当前字符串长度,切记不能在 while 循环时记录长度,会陷入只有在删除重复元素时才会更新长度。

2.2 解法

i)定义变量

ii)统计 right 所指元素的数量

iii)进行判断,如果重复则通过移动 left 和 while 循环跳过重复元素

iiii)记录长度

2.3 代码实现

java 复制代码
class Solution {
    public int lengthOfLongestSubstring(String ss) {
        int n = ss.length(),ret = 0;
        int[] hash = new int[128];
        char[] s = ss.toCharArray();
        for(int left = 0,right =0;right<n;right++){
            hash[s[right]]++;
            while(hash[s[right]]>1){
                hash[s[left++]]--;
            }
            ret = Math.max(ret,right-left+1);
            

        }
        return ret;

    }
}
相关推荐
忘了ʷºᵇₐ5 小时前
在IDEA 2024.1版本中如何打开Remote Host及连接linux
linux·运维·服务器
零K沁雪6 小时前
Linux 内核中与网络地址相关的函数
linux·内核
steins_甲乙8 小时前
# 从 0 做一个小型内存泄漏检测器:开篇与架构设计
linux
蒸蒸yyyyzwd9 小时前
后端学习笔记 day4
linux·笔记·学习
upp10 小时前
[最新版本centos 10系统制作与安装]
linux·运维·centos
一战成名99610 小时前
ToDesk全球节点 vs TeamViewer、AnyDesk延迟与稳定性对比
运维·服务器·teamviewer
ShineWinsu10 小时前
对于Linux:进程优先级、进程切换以及进程调度的解析
linux·面试·笔试·进程·进程切换·进程调度·进程优先级
Kira Skyler11 小时前
kprobe函数入口时的汇编跳板执行流程与栈帧机制
linux·汇编
桌面运维家11 小时前
VHD/VHDX 数据守护:BAT位图校验与修复
linux·服务器·网络
pupudawang11 小时前
Linux下安装Nginx服务及systemctl方式管理nginx详情
linux·运维·nginx