优选算法 - 1 ( 双指针 移动窗口 8000 字详解 )

news2024/11/13 11:41:08

一:双指针

1.1 移动零

题目链接:283.移动零

在这里插入图片描述

在这里插入图片描述

class Solution {
    public void moveZeroes(int[] nums) {
        for(int cur = 0, dest = -1 ; cur < nums.length ; cur++){
            if(nums[cur] == 0){
            }else{
                dest++; // dest 先向后移动⼀位
                int tmp = nums[cur];
                nums[cur] = nums[dest];
                nums[dest] = tmp;
            }
        }
        
    }
}

在这里插入图片描述

这类题目的本质就是数组划分,根据某个规则将数组分成若干个区间,在此题中,我们可以使用双指针算法划分数组的区间,用数组下标充当指针,两个指针会划分成3个区间

1.2 复写零

题目链接:复写零

在这里插入图片描述

请添加图片描述

class Solution {
    public void duplicateZeros(int[] arr) {
        int length = arr.length;
        int cur = 0; // 最后一个复写数的长度
        int i;

        // 第一步:先获取最后一个复写数的索引
        for (i = 0; i < length; i++) {
            if (arr[i] == 0) {
                cur += 2;  // 遇到 0 占两个位置
            } else {
                cur++;  // 非 0 占一个位置
            }
            if (cur >= length) {
                break;
            }
        }

        // 第二步:开始操作,从右向左复制数据
        int dest = length - 1;
        
        // 细节:检查最后一个位置是否是一个完整的 0
        if (cur > length) {
            if (arr[i] == 0) {
                arr[dest--] = 0; // 如果 cur 超过数组长度,最后一个 0 只复制一次,防止越界
            }
            i--; // 减少 i 以便继续处理剩下的部分
        }

        // 从右到左进行实际复制
        while (i >= 0) {
            if (arr[i] == 0) {
                arr[dest--] = 0; // 复制第一个 0
                arr[dest--] = 0; // 复制第二个 0
            } else {
                arr[dest--] = arr[i]; // 复制非零元素
            }
            i--;
        }
    }
}

在这里插入图片描述

1.3 快乐数

题目链接:快乐数
在这里插入图片描述

请添加图片描述

class Solution {
    
    //封装一个求 n 每一位的平方和的函数
    public int bitsum(int n){
        int sum = 0;
        while(n > 0){
            int bit = n % 10;
            sum += bit * bit;
            n /= 10;
        }
        return sum;
    }

    public boolean isHappy(int n) {
        //先让快指针走一步
        int slow = n;
        int fast = bitsum(n);

        while(slow != fast){
            //慢指针走一步,快指针走两步
             slow = bitsum(slow);
             fast = bitsum(bitsum(fast));
        }      
        return fast == 1;
    }
}

在这里插入图片描述

1.4 盛水最多的容器

题目链接: 盛水最多的容器

在这里插入图片描述

请添加图片描述

class Solution {
    public int maxArea(int[] height) {
        // left 是左指针, right 是右指针,ret存储最大的体积结果
        int left = 0;
        int right = height.length - 1;
        int ret = 0;

        while(left < right){
            int v = Math.min(height[left], height[right]) * (right - left);
            ret = Math.max(ret,v);

            if(height[left] < height[right]) left++;
            else right --;
        }
        return ret;
    }
}

在这里插入图片描述

1.5 有效三角形的个数

题目链接:有效三角形的个数

在这里插入图片描述
请添加图片描述

class Solution {
    public int triangleNumber(int[] nums) {
        //首先先对数组排序,并用 ret 存储有效三角形的个数
        Arrays.sort(nums);
        int ret= 0;
        int n = nums.length - 1;

        //先固定一个最大的数,最大的数最小的下标应该是 2
        for(int i = n ; i >= 2 ; i --){
            int left = 0;
            int right = i - 1;
            
            while (left < right) {    
                //如果左指针加上右指针的值大于固定数的值
                if(nums[left] + nums[right] > nums[i]){
                    ret += (right - left);
                    right--;
                }else{
                    left++;
                }
            }    
            
        }
        return ret;
    }
}

在这里插入图片描述

1.6 和为 s 的两个数字

题⽬链接:和为s的两个数字

在这里插入图片描述
请添加图片描述

class Solution
{
    public int[] twoSum(int[] nums, int target)
    {
        int left = 0, right = nums.length - 1;
        while(left < right){
            int sum = nums[left] + nums[right];
            if(sum > target) right--;
            else if(sum < target) left++;
            else return new int[] {nums[left], nums[right]};
        }
    // 照顾编译器
    return new int[]{0};
    }
}

在这里插入图片描述

1.7 三数之和

题目链接:三数之和

在这里插入图片描述

请添加图片描述

import java.util.*;

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        // 先对数组进行排序
        Arrays.sort(nums);
        List<List<Integer>> ret = new ArrayList<>();
        int n = nums.length;

        // 固定一个数,从左往右固定,最少保留两个数
        for (int i = 0; i < n - 2; i++) {
            // 跳过固定数的重复情况
            if (i > 0 && nums[i] == nums[i - 1]) continue;

            int left = i + 1, right = n - 1, target = -nums[i];

            while (left < right) {
                int sum = nums[left] + nums[right];

                if (sum > target)  right--; 
                else if (sum < target)  left++;
                else {
                    // 找到符合条件的三元组
                    ret.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    left++; right--;

                    // 跳过重复的 left 和 right 元素,防止结果重复
                    while (left < right && nums[left] == nums[left - 1]) left++;
                    while (left < right && nums[right] == nums[right + 1]) right--;
                }
            }
        }

        return ret;
    }
}

在这里插入图片描述

1.8 四数之和

题目链接:四数之和

在这里插入图片描述

请添加图片描述

import java.util.*;

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        //先对数组进行排序
        Arrays.sort(nums);
        int n = nums.length;
        List<List<Integer>> ret = new ArrayList<>();

        //接着固定两个数
        for(int i = 0 ; i < n   ;){
            for(int j = i + 1 ; j < n ; ){
                int left = j + 1 , right = n - 1;
                long aim = (long)target - nums[i] - nums[j];

                while(left < right){
                    int sum = nums[left] + nums[right];
                    if(sum > aim) right--;
                    else if(sum < aim) left++;
                    else{
                        ret.add(Arrays.asList(nums[i], nums[j], nums[left++],nums[right--]));
                        //接着进行去重
                        while(left < right && nums[left] == nums[left - 1]) left++;
                        while(left < right && nums[right] == nums[right + 1]) right--;
                    }
                }
                
                //循环执行完毕后,让第二个固定的数加 1
                j++;
                while(j < n && nums[j] == nums[j - 1]) j++;
            }
            i++;
            while(i < n && nums[i] == nums[i - 1]) i++;
        }

        return ret;
    }
}

在这里插入图片描述

二: 移动窗口

2.1 长度最小的子数组

题目链接:长度最小的子数组

在这里插入图片描述

请添加图片描述

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        // size 用于记录最小子数组的长度,sum 用于存储子数组的和
        int n = nums.length, sum = 0, size = Integer.MAX_VALUE;
        int left = 0, right = 0;

        while(right < n){
            //进窗口
            sum += nums[right];
            //出窗口
            while(sum >= target){
                size = Math.min(size,right - left + 1);
                sum -= nums[left++];
            } 
            //一次迭代完成后让右指针继续走
            right++;
        }

        //判断一下 size 是否被更新过
        return size == Integer.MAX_VALUE ? 0 : size;
    }
}

在这里插入图片描述

2.2 无重复字符的最长子串

题目链接:无重复字符的最长子串

在这里插入图片描述

请添加图片描述

class Solution {
    public int lengthOfLongestSubstring(String ss) {
        //先把字符转为字符数组
       char[] s = ss.toCharArray();
       //用数组模拟一个哈希表
       int[] hash = new int[128];
       int left = 0, right = 0 , n = ss.length();
       int maxsize = 0;

       while(right < n){
            //进窗口,先拿到下标为 left 的字符,让这个字符所在的 hash 数组中的位置的值 +1 ,代表这个字符已经存入
            hash[s[right]]++;
            //出窗口
            while(hash[s[right]] > 1){
                hash[s[left]]--;
                left++;
            }

            maxsize = Math.max(maxsize,right - left + 1);
            right++;
       }

       return maxsize;
    }
}

在这里插入图片描述

2.3 最大连续 1 的个数 III

题目链接:最大连续 1 的个数 III

在这里插入图片描述
请添加图片描述

class Solution {
    public int longestOnes(int[] nums, int k) {
        //定义左右指针和计数器 zero ,用于统计 0 的个数
        int left = 0, right = 0 ,zero = 0, n = nums.length,ret = 0;
        while(right < n){
            //进窗口
            if(nums[right] == 0) zero++;
            //出窗口
            while(zero > k){               
                if(nums[left++] == 0) zero--;
            }
            ret = Math.max(ret,right - left + 1);
            right++;
        }
        return ret;
    }
}

在这里插入图片描述

2.4 将 x 减到 0 的最小操作数

题目链接:将 x 减到 0 的最小操作数

在这里插入图片描述

请添加图片描述

class Solution {
    public int minOperations(int[] nums, int x) {
        int sum = 0, left = 0, right = 0, n = nums.length;
        for(int a : nums) sum += a;
        int target = sum - x , total = 0, len = -1;

        // 如果 target 小于 0,直接返回 -1
        if (target < 0) return -1;  
        while(right < n){
            //进窗口
            total += nums[right];

            //出窗口
            while(total > target) total -= nums[left++];

            //更新 len
            if(total == target) len = Math.max(len,right - left + 1);

            right++;
        }
        if(len == -1) return len;
        else return n - len;
    }
}

在这里插入图片描述

2.5 水果成篮

题目链接:水果成篮

在这里插入图片描述

请添加图片描述

class Solution {
    public int totalFruit(int[] fruits) {
        //创建一个哈希表,用于存储水果的种类和数量
        Map<Integer, Integer> hash = new HashMap<>();
        int left = 0, right = 0, n = fruits.length, max = 0;

        while(right < n){
            //进窗口
            int ch1 = fruits[right];
            hash.put(ch1, hash.getOrDefault(ch1,0) + 1);

            //出窗口
            while(hash.size() > 2){
                int ch2 = fruits[left];
                hash.put(ch2, hash.get(ch2) - 1); 
                //踢出元素的时候,可能会让这个元素变空,此时要踢出去
                if(hash.get(ch2) == 0) hash.remove(ch2);
                left++;
            }

            //更新结果
            max = Math.max(max, right - left + 1);
            right++;
        }
        return max;
    }
}

2.6 找到字符串中所有字母异位词

题目链接:找到字符串中所有字母异位词

在这里插入图片描述

请添加图片描述
请添加图片描述

class Solution {
    public List<Integer> findAnagrams(String ss, String pp) {
        List<Integer> ret = new ArrayList<>();
        //不合理的情况,直接返回一个空的
        if(pp.length() > ss.length()) return ret;

        //接着把 s 和 p 转换为字符数组,并用 hash1 和 hash2 分别记录 s 和 p 中出现过的字符和次数,count 统计有效字符的个数
        char[] s = ss.toCharArray();
        char[] p = pp.toCharArray();
        int[] hash1 = new int[26];
        int[] hash2 = new int[26];
        for(int ch : p) hash2[ch - 'a']++;

        int left = 0, right = 0, count = 0, n = s.length;
        while(right < n){
            //进窗口 + 维护 count
            char in = s[right];
            hash1[in - 'a']++;
            if(hash1[in - 'a'] <= hash2[in - 'a']) count ++;

            //出窗口 + 维护 count
            
            if(right - left + 1 > p.length) {
                char out = s[left];
                //这两行可以合并,但是为了代码的可读性就不进行合并了
                hash1[out - 'a']--;
                if(hash1[out -'a'] < hash2[out - 'a']) count--;
                left++;
            } 

            //更新结果
            if(count == p.length) ret.add(left);
            right++;
        }
        
        return ret;
    }
}

在这里插入图片描述

2.7 串联所有单词的子串

题目链接:串联所有单词的子串

在这里插入图片描述

请添加图片描述

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> ret = new ArrayList<>();
        if (words.length == 0 || s.length() < words.length * words[0].length()) return ret;

        // 存储 words 中每个字符串的频率
        Map<String, Integer> hash1 = new HashMap<>();
        for (String str : words) {
            hash1.put(str, hash1.getOrDefault(str, 0) + 1);
        }

        int len = words[0].length(), m = words.length, windowSize = len * m;

        // 遍历所有可能的起始点
        for (int i = 0; i < len; i++) {
            Map<String, Integer> hash2 = new HashMap<>();
            int left = i, right = i, count = 0;

            // 滑动窗口
            while (right + len <= s.length()) {
                String in = s.substring(right, right + len);
                right += len;

                // 更新窗口内单词频率计数
                hash2.put(in, hash2.getOrDefault(in, 0) + 1);

                // 如果 in 的频率不超过 hash1 中的频率,增加 count
                if (hash2.get(in) <= hash1.getOrDefault(in, 0)) {
                    count++;
                }

                // 当窗口大小等于 windowSize 时,检查并可能出窗口
                if (right - left == windowSize) {
                    if (count == m) ret.add(left); // 找到符合条件的子串

                    String out = s.substring(left, left + len);
                    left += len;

                    // 更新窗口内单词频率计数
                    if (hash2.get(out) <= hash1.getOrDefault(out, 0)) {
                        count--;
                    }
                    hash2.put(out, hash2.get(out) - 1);

                    // 如果频率为 0,从 hash2 中移除该单词
                    if (hash2.get(out) == 0) {
                        hash2.remove(out);
                    }
                }
            }
        }

        return ret;
    }
}

在这里插入图片描述

2.8 最小覆盖子串

题目链接:最小覆盖子串

在这里插入图片描述

请添加图片描述

class Solution {
    public String minWindow(String ss, String tt) {
        // 将字符串转换成字符数组
        char[] s = ss.toCharArray();
        char[] t = tt.toCharArray();
        
        // 用 hash1 存储字符串 t 中每个字符的频率
        int[] hash1 = new int[128];
        int uniqueChars = 0; // 统计 t 中不同字符的种类数
        for (char ch : t) {
            if (hash1[ch]++ == 0) uniqueChars++;
        }

        // hash2 用来统计窗口内的字符频率
        int[] hash2 = new int[128];
        int minLen = Integer.MAX_VALUE, start = -1;
        
        int left = 0, matchedCount = 0;

        // 右指针移动
        for (int right = 0; right < s.length; right++) {
            char in = s[right];
            hash2[in]++;

            // 如果当前字符频率与 t 中相等,则增加匹配计数
            if (hash2[in] == hash1[in]) matchedCount++;

            // 当所有字符频率匹配时,尝试收缩窗口
            while (matchedCount == uniqueChars) {
                // 如果当前窗口更小,则更新最小窗口的长度和起始位置
                if (right - left + 1 < minLen) {
                    minLen = right - left + 1;
                    start = left;
                }

                // 出窗口
                char out = s[left++];
                if (hash2[out] == hash1[out]) matchedCount--;
                hash2[out]--;
            }
        }

        // 根据最小窗口的位置和长度返回结果
        return start == -1 ? "" : ss.substring(start, start + minLen);
    }
}

在这里插入图片描述

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

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

相关文章

鸿蒙操作系统是什么?与安卓系统有什么区别?

鸿蒙操作系统 鸿蒙操作系统&#xff08;HarmonyOS&#xff09;是华为公司发布的一款基于微内核的面向全场景的分布式操作系统。 发展历程&#xff1a; 早期规划&#xff1a;华为从2012 年开始规划自有操作系统&#xff0c;并在芬兰赫尔辛基设立智能手机研发中心&#xff0c;招…

现场工程师日记-MSYS2迅速部署PostgreSQL主从备份数据库

文章目录 一、概要二、整体架构流程1. 安装 MSYS2 环境2. 安装postgresql 三、技术名词解释1.MSYS22.postgresql 四、技术细节1. 创建主数据库2.添加从数据库复制权限3. 按需修改参数&#xff08;1&#xff09;WAL保留空间&#xff08;2&#xff09;监听地址 4. 启动主服务器5.…

第二届计算机网络技术与电子信息工程国际学术会议(CNTEIE 2024,12月6-8日)

第二届计算机网络技术与电子信息工程国际学术会议&#xff08;CNTEIE 2024&#xff09; 2024 2nd International Conference on Computer Network Technology and Electronic and Information Engineering 重要信息 会议官网&#xff1a;www.cnteie.org 2024 2nd Internation…

Git 入门篇(一)

前言 操作系统&#xff1a;win11 64位 与gitee搭配使用 Git 入门篇&#xff08;一&#xff09; Git 入门篇&#xff08;二&#xff09; Git 入门篇&#xff08;三&#xff09; 目录 git下载、安装与配置 下载 安装 配置 git下载、安装与配置 下载 官网&#xff1a;git-…

WPS文档中的“等线”如何删除

如何删除“等线”占用的行如何删除表格之间的空行WPS文档中的“等线”是什么如果删除脚注文本占用的行 如下这种&#xff0c;在文档中添加了表格和脚注&#xff0c;发现上下表格之间有多行空行&#xff0c;鼠标选中&#xff0c;显示是“等线”&#xff0c;那么如何去除等线占用…

题目讲解15 合并两个排序的链表

原题链接&#xff1a; 合并两个排序的链表_牛客题霸_牛客网 思路分析&#xff1a; 第一步&#xff1a;写一个链表尾插数据的方法。 typedef struct ListNode ListNode;//申请结点 ListNode* BuyNode(int x) {ListNode* node (ListNode*)malloc(sizeof(ListNode));node->…

计算机网络基本概念总结

IP地址 概念 使网络中的设备都有唯一的地址标识&#xff0c;用于表示其在网络中的位置。 格式 IP地址是一个32位的二进制数&#xff0c;通常被分割为4个8位二进制数&#xff08;也就是4个字节&#xff09;&#xff0c;如&#xff1a;01100100.00001000.00001010.00000110。通常…

Pandas | 特征列大量数据异常需要填充数据时注意事项

问题描述 一组数据如下&#xff1a; df.isnull().sum()城市 0 名称 0 星级 1529 评分 0 价格 1 销量 1 省/市/区 0 坐标 0 简介 41 是否免费 0 具体地址 3 dtype: int64df[星级]0…

Science Robotics 综述揭示演化研究新范式,从机器人复活远古生物!

在地球46亿年的漫长历史长河中&#xff0c;生命的演化过程充满着未解之谜。如何从零散的化石证据中还原古生物的真实面貌&#xff1f;如何理解关键演化节点的具体过程&#xff1f;10月23日&#xff0c;Science Robotics发表重磅综述&#xff0c;首次系统性提出"古生物启发…

[编译报错]ImportError: No module named _sqlite3解决办法

1. 问题描述&#xff1a; 在使用python进行代码编译时&#xff0c;提示下面报错&#xff1a; "/home/bspuser/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py", line 18, in <module>import sqlite3File "/usr/local/lib/python2.7/sqlite3/_…

EasyExcel的AbstractColumnWidthStyleStrategy注入CellStyle不生效

设置背景色 CellStyle style workbook.createCellStyle();style.setFillForegroundColor(IndexedColors.RED.getIndex()); // 是设置前景色不是背景色style.setFillPattern(FillPatternType.SOLID_FOREGROUND)EasyExcel.writerTable(0).head(Head1.class).registerWriteHandl…

iphone怎么删除重复的照片的新策略

Phone用户常常面临存储空间不足的问题&#xff0c;其中一个主要原因是相册中的重复照片。这些重复项不仅占用了大量的存储空间&#xff0c;还会影响设备的整体性能。本文将向您展示iphone怎么删除重复的照片的方法&#xff0c;包括一些利用工具来自动化这个过程的创新方法。 识…

AI4SCIENSE(鄂维南院士:再谈AI for Science)

鄂维南院士&#xff1a;再谈AI for Science_哔哩哔哩_bilibili 以往处理高维问题 量子力学&#xff1a;单变量乘积 统计学&#xff1a;旋转 AI4S 处理数据 蛋白质折叠&#xff1f; 不是纯粹的数据驱动 物理学等学科基本原理 例&#xff1a;分子动力学 数据模型 流程图 这…

learn C++ NO.31——类型转换

C语言中的类型转换 在C语言中&#xff0c;当赋值符号两边的类型不匹配的时候&#xff0c;或者是形参类型和实参类型不匹配时&#xff0c;返回值类型与接受返回值类型不匹配时&#xff0c;都会需要类型转换。C语言的类型转换有两种&#xff1a;显示类型转换和隐式类型转换。 显…

基于Spring Boot的养老保险管理系统的设计与实现,LW+源码+讲解

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统养老保险管理系统信息管理难度大&#xff0c;容错率低&a…

w029基于springboot的网上购物商城系统研发

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0…

Unet++改进8:添加SpatialGroupEnhance||空间群智能增强:改进卷积网络中的语义特征学习

本文内容:添加SpatialGroupEnhance 论文简介 卷积神经网络(Convolutional Neural Networks, cnn)通过收集分层的、不同部分的语义子特征来生成复杂对象的特征表示。这些子特征通常以分组的形式分布在每一层的特征向量中[43,32],代表各种语义实体。然而,这些子特征的激活往往…

十八:Spring Boot 依赖(3)-- spring-boot-starter-data-jpa 依赖详解

目录 1. 理解 JPA&#xff08;Java Persistence API&#xff09; 1.1 什么是 JPA&#xff1f; 1.2 JPA 与 Hibernate 的关系 1.3 JPA 的基本注解&#xff1a;Entity, Table, Id, GeneratedValue 1.4 JPA 与数据库表的映射 2. Spring Data JPA 概述 2.1 什么是 Spring Dat…

MQTT协议解析 : 物联网领域的最佳选择

1. MQTT协议概述 1.1 MQTT协议是什么 MQTT : Message Queuing Telemetry Transport 模式 : 发布 / 订阅主题优点 : 代码量小、低带宽、实时可靠应用 : 物联网、小型设备、移动应用MQTT 常用端口 : 1883 MQTT是一个网络协议&#xff0c;和HTTP类似&#xff0c;因为轻量简单&…

Pytorch实现transformer语言模型

转载自&#xff1a;| 03_language_model/02_Transformer语言模型.ipynb | 从头训练Transformer语言模型 |Open In Colab | Transformer语言模型 本节训练一个 sequence-to-sequence 模型&#xff0c;使用pytorch的 nn.Transformer <https://pytorch.org/docs/master/nn.ht…