【优选算法】(第八篇)

news2024/9/28 18:38:33

目录

串联所有单词的⼦串(hard)

题目解析

讲解算法原理

编写代码

最⼩覆盖⼦串(hard)

题目解析

讲解算法原理

编写代码


串联所有单词的⼦串(hard)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给定⼀个字符串s和⼀个字符串数组words。words中所有字符串⻓度相同。
s中的串联⼦串是指⼀个包含words中所有字符串以任意顺序排列连接起来的⼦串。
◦ 例如,如果words=[)ab),)cd),)ef)],那
么)abcdef),)abefcd),)cdabef),)cdefab),)efabcd),和)efcdab)都是串联⼦串。)acdbef)不是串联⼦串,因为他不是任何words排列的连接。
返回所有串联字串在s中的开始索引。你可以以任意顺序返回答案。
⽰例1:
输⼊:s=)barfoothefoobarman),words=[)foo),)bar)]输出:[0,9]
解释:因为words.length==2同时words[i].length==3,连接的⼦字符串的⻓度必须为6。⼦串)barfoo)开始位置是0。它是words中以[)bar),)foo)]顺序排列的连接。
⼦串)foobar)开始位置是9。它是words中以[)foo),)bar)]顺序排列的连接。输出顺序⽆关紧要。返回[9,0]也是可以的。
⽰例2:
输⼊:s=)wordgoodgoodgoodbestword),words=[)word),)good),)best),)word)]输出:[]
解释:因为words.length==4并且words[i].length==4,所以串联⼦串的⻓度必须为16。s中没有⼦串⻓度为16并且等于words的任何顺序排列的连接。
所以我们返回⼀个空数组。
⽰例3:
输⼊:s=)barfoofoobarthefoobarman),words=[)bar),)foo),)the)]输出:[6,9,12]
解释:因为words.length==3并且words[i].length==3,所以串联⼦串的⻓度必须为9。⼦串)foobarthe)开始位置是6。它是words中以[)foo),)bar),)the)]顺序排列的连接。⼦串)barthefoo)开始位置是9。它是words中以[)bar),)the),)foo)]顺序排列的连接。⼦串)thefoobar)开始位置是12。它是words中以[)the),)foo),)bar)]顺序排列的连接。

提⽰:
1<=s.length<=104
1<=words.length<=5000
1<=words[i].length<=30
words[i]和s由⼩写英⽂字⺟组成

讲解算法原理

解法⼀(暴⼒解法):
算法思路:
如果我们把每⼀个单词看成⼀个⼀个字⺟,问题就变成了找到「字符串中所有的字⺟异位词」。⽆⾮就是之前处理的对象是⼀个⼀个的字符,我们这⾥处理的对象是⼀个⼀个的单词。

编写代码

c++算法代码:

class Solution
{
public:
 vector<int> findSubstring(string s, vector<string>& words) 
 {
 vector<int> ret;
 unordered_map<string, int> hash1; // 保存 words ⾥⾯所有单词的频次
 for(auto& s : words) hash1[s]++;
 int len = words[0].size(), m = words.size();
 for(int i = 0; i < len; i++) // 执⾏ len 次
 {
 unordered_map<string, int> hash2; // 维护窗⼝内单词的频次
 for(int left = i, right = i, count = 0; right + len <= s.size(); 
right += len)
 {
 // 进窗⼝ + 维护 count
 string in = s.substr(right, len);
 hash2[in]++;
 if(hash1.count(in) && hash2[in] <= hash1[in]) count++;
 // 判断
 if(right - left + 1 > len * m)
 {
 // 出窗⼝ + 维护 count
 string out = s.substr(left, len);
 if(hash1.count(out) && hash2[out] <= hash1[out]) count--;
 hash2[out]--;
 left += len;
 }
 // 更新结果
 if(count == m) ret.push_back(left);
 }
 }
 return ret;
 }
};

java算法代码:

class Solution
{
 public List<Integer> findSubstring(String s, String[] words) 
 {
 List<Integer> ret = new ArrayList<Integer>();
 // 保存字典中所有单词的频次
 Map<String, Integer> hash1 = new HashMap<String, Integer>(); 
 for(String str : words) hash1.put(str, hash1.getOrDefault(str, 0) + 1);
 int len = words[0].length(), m = words.length;
 for(int i = 0; i < len; i++) // 执⾏次数
 {
 // 保存窗⼝内所有单词的频次
 Map<String, Integer> hash2 = new HashMap<String, Integer>(); 
 for(int left = i, right = i, count = 0; right + len <= s.length(); 
right += len)
 {
 // 进窗⼝ + 维护 count
 String in = s.substring(right, right + len);
 hash2.put(in, hash2.getOrDefault(in, 0) + 1);
 if(hash2.get(in) <= hash1.getOrDefault(in, 0)) count++; 
 // 判断
 if(right - left + 1 > len * m)
 {
 // 出窗⼝ + 维护 count
 String out = s.substring(left, left + len);
 if(hash2.get(out) <= hash1.getOrDefault(out, 0)) count--;
 hash2.put(out, hash2.get(out) - 1);
 left += len;
 }
 // 更新结果
 if(count == m) ret.add(left);
 }
 }
 return ret;
 }
}

最⼩覆盖⼦串(hard)

题目解析

1.题目链接:. - 力扣(LeetCode)

2。题目描述

给你⼀个字符串s、⼀个字符串t。返回s中涵盖t所有字符的最⼩⼦串。如果s中不存在涵盖t所有字符的⼦串,则返回空字符串""。
注意:
对于t中重复字符,我们寻找的⼦字符串中该字符数量必须不少于t中该字符数量。如果s中存在这样的⼦串,我们保证它是唯⼀的答案。
⽰例1:
输⼊:s=)ADOBECODEBANC),t=)ABC)输出:)BANC)
解释:
最⼩覆盖⼦串)BANC)包含来⾃字符串t的*A*、*B*和*C*。⽰例2:
输⼊:s=)a),t=)a)输出:)a)
解释:
整个字符串s是最⼩覆盖⼦串。⽰例3:
输⼊:s=)a),t=)aa)输出:""
解释:
t中两个字符*a*均应包含在s的⼦串中,
因此没有符合条件的⼦字符串,返回空字符串。

讲解算法原理

解法(滑动窗⼝+哈希表):
算法思路:
◦ 研究对象是连续的区间,因此可以尝试使⽤滑动窗⼝的思想来解决。
◦ 如何判断当前窗⼝内的所有字符是符合要求的呢?
我们可以使⽤两个哈希表,其中⼀个将⽬标串的信息统计起来,另⼀个哈希表动态的维护窗⼝内字符串的信息。
当动态哈希表中包含⽬标串中所有的字符,并且对应的个数都不⼩于⽬标串的哈希表中各个字符的个数,那么当前的窗⼝就是⼀种可⾏的⽅案。
算法流程:
a. 定义两个全局的哈希表: 1 号哈希表 hash1 ⽤来记录⼦串的信息, 2 号哈希表 hash2
⽤来记录⽬标串 t 的信息;
b. 实现⼀个接⼝函数,判断当前窗⼝是否满⾜要求:
i. 遍历两个哈希表中对应位置的元素:
• 如果 t 中某个字符的数量⼤于窗⼝中字符的数量,也就是 2 号哈希表某个位置⼤于
1 号哈希表。说明不匹配,返回 false ;
• 如果全都匹配,返回 true 。
主函数中:
a. 先将 t 的信息放⼊ 2 号哈希表中;
b. 初始化⼀些变量:左右指针: left = 0,right = 0 ;⽬标⼦串的⻓度: len = 
INT_MAX ;⽬标⼦串的起始位置: retleft ;(通过⽬标⼦串的起始位置和⻓度,我们就能找到结果)
c. 当 right ⼩于字符串 s 的⻓度时,⼀直下列循环:
i. 将当前遍历到的元素扔进 1 号哈希表中;
ii. 检测当前窗⼝是否满⾜条件:
• 如果满⾜条件:
◦ 判断当前窗⼝是否变⼩。如果变⼩:更新⻓度 len ,以及字符串的起始位置
retleft ;
◦ 判断完毕后,将左侧元素滑出窗⼝,顺便更新 1 号哈希表;
◦ 重复上⾯两个过程,直到窗⼝不满⾜条件;
iii. right++ ,遍历下⼀个元素;
d. 判断 len 的⻓度是否等于 INT_MAX :
i. 如果相等,说明没有匹配,返回空串;
ii. 如果不想等,说明匹配,返回 s 中从 retleft 位置往后 len ⻓度的字符串。

编写代码

c++算法代码:

class Solution
{
public:
 string minWindow(string s, string t) 
 {
 int hash1[128] = { 0 }; // 统计字符串 t 中每⼀个字符的频次
 int kinds = 0; // 统计有效字符有多少种
 for(auto ch : t)
 if(hash1[ch]++ == 0) kinds++;
 int hash2[128] = { 0 }; // 统计窗⼝内每个字符的频次
 int minlen = INT_MAX, begin = -1;
 for(int left = 0, right = 0, count = 0; right < s.size(); right++)
 {
 char in = s[right];
 if(++hash2[in] == hash1[in]) count++; // 进窗⼝ + 维护 count
 while(count == kinds) // 判断条件
 {
 if(right - left + 1 < minlen) // 更新结果
 {
 minlen = right - left + 1;
 begin = left;
 }
 char out = s[left++];
 if(hash2[out]-- == hash1[out]) count--; // 出窗⼝ + 维护 count }
 }
 if(begin == -1) return "";
 else return s.substr(begin, minlen);
 }
};

java算法代码:

class Solution {
 public String minWindow(String ss, String tt) {
 char[] s = ss.toCharArray();
 char[] t = tt.toCharArray();
 int[] hash1 = new int[128]; // 统计字符串 t 中每⼀个字符的频次
 int kinds = 0; // 统计有效字符有多少种
 for(char ch : t)
 if(hash1[ch]++ == 0) kinds++;
 int[] hash2 = new int[128]; // 统计窗⼝内每个字符的频次
 int minlen = Integer.MAX_VALUE, begin = -1;
 for(int left = 0, right = 0, count = 0; right < s.length; right++)
 {
 char in = s[right];
 if(++hash2[in] == hash1[in]) count++; // 进窗⼝ + 维护 count
 while(count == kinds) // 判断条件
 {
 if(right - left + 1 < minlen) // 更新结果
 {
 minlen = right - left + 1;
 begin = left;
 }
 char out = s[left++];
 if(hash2[out]-- == hash1[out]) count--; // 出窗⼝ + 维护 count }
 }
 if(begin == -1) return new String();
 else return ss.substring(begin, begin + minlen);
 }
}

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

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

相关文章

防砸安全鞋这样挑,舒适又安心!

在复杂多变的工作环境中&#xff0c;安全始终放在首位&#xff0c;特别是对于那些在工地、车间等危险环境中工作的朋友们来说&#xff0c;一双好的防砸安全鞋无疑是工作中的“守护神”。然而&#xff0c;市面上的防砸安全鞋种类繁多&#xff0c;如何挑选一双既舒适又安心的鞋子…

unreal engine5制作动作类游戏时,我们使用刀剑等武器攻击怪物或敌方单位时,发现攻击特效、伤害等没有触发

UE5系列文章目录 文章目录 UE5系列文章目录前言一、问题分析二、解决方法1. 添加项目设置碰撞检测通道2.玩家角色碰撞设置3.怪物角色碰撞预设 最终效果 前言 在使用unreal engine5制作动作类游戏时&#xff0c;我们使用刀剑等武器攻击怪物或敌方单位时&#xff0c;发现攻击特效…

10.C++程序中的循环语句

C中提供了三种循环语句&#xff08;for循环&#xff0c;while循环以及do-while循环)来使程序员可以更方便地对数据进行迭代操作。 if语句 for语句的格式为&#xff1a; for(初始化语句&#xff1b;循环条件&#xff1b;迭代语句&#xff09; &#xff5b; 代码块 &#x…

网上找旅游搭子靠谱吗?分享国庆与旅行搭子出行的冒险记

国庆将至&#xff0c;我那颗渴望旅行的心愈发躁动不安。一直想在这个难得的假期里去领略祖国的大好河山&#xff0c;思来想去&#xff0c;决定去神秘而美丽的张家界。然而&#xff0c;身边的朋友不是已有安排&#xff0c;就是对这个目的地不感兴趣。无奈之下&#xff0c;我只好…

ArcGIS与ArcGIS Pro去除在线地图服务名单

我们之前给大家分享了很多在线地图集&#xff0c;有些地图集会带有制作者信息&#xff0c;在布局制图的时候会带上信息影响出图美观。 一套GIS图源集搞定&#xff01;清新规划底图、影像图、境界、海洋、地形阴影图、导航图 比如ArcGIS&#xff1a; 比如ArcGIS Pro&#xff1a…

书生大模型实战(从入门到进阶)L2-茴香豆:企业级知识库问答工具

目录 茴香豆介绍 茴香豆本地标准版搭建 环境搭建 配置服务器&#xff1a; 搭建茴香豆虚拟环境&#xff1a; 安装茴香豆 下载茴香豆 安装茴香豆所需依赖 下载模型文件 更改配置文件 知识库创建 测试知识助手 命令行运行 Gradio UI 界面测试 本文是对书生大模型L2-茴香…

电脑录屏怎么录视频和声音?苹果macOS、windows10都可以用的原神录屏工具来啦

在当今数字化时代&#xff0c;电脑录屏已经成为一项非常实用的技能&#xff0c;无论是制作教学视频、记录游戏精彩瞬间&#xff0c;还是进行线上会议演示&#xff0c;都离不开高质量的录屏。那么&#xff0c;电脑录屏怎么录视频和声音呢&#xff1f;今天就为大家详细介绍一下&a…

<<迷雾>> 第 2 章 用电来表示数 示例电路

开关的通断对应着1和0 info::操作说明 鼠标单击开关切换开合状态 primary::在线交互操作链接 https://cc.xiaogd.net/?startCircuitLinkhttps://book.xiaogd.net/cyjsjdmw-examples/assets/circuit/cyjsjdmw-ch02-01-represent-number-by-switch.txt 原图 通过使用多个开关、可…

数据结构与算法——Java实现 21.栈

目录 一、概述 二、基于链表的栈的实现 接口 链表接口实现类 测试类 ​编辑 三、基于数组的栈的实现 接口 数组接口实现类 测试类 妈妈&#xff0c;生日快乐&#xff0c;希望你健康快乐没有烦恼也不会有病痛 —— 24.9.28 一、概述 计算机科学中&#xff0c;stack是一种线性的…

构造性神经组合优化的学习编码需要反悔

文章目录 Abstract1 Introduction2 Related Work用于构造性启发式的深度强化学习当前用于更好编码的方法3 LCH-Regret学习构造性启发式反悔机制LCH - Regret 机制的 L R L_R LR​Abstract 深度强化学习的神经组合优化中,学习构造性启发式(LCH)通过快速的自回归解构建过程实…

Redis中String类型的常用命令(append,getrenge,setrange等命令)

Redis----String命令 前言.常见的String存储类型. 常见命令1. set 命令2. get 命令3. mget命令与mset命令4. setnx命令5. setex与psetex命令6. incr与incrby与incrbyfloat命令7. decr与decrby命令8. append命令9. getrange和setrange命令10. strlen命令. 前言. 常见的String存…

《开题报告》基于SpringBoot框架的高校专业实习管理系统开题报告的设计与实现源码++学习文档+答辩讲解视频

开题报告 研究背景 在当今高等教育日益普及与深化的背景下&#xff0c;高校专业实习作为学生将理论知识转化为实践能力、提前适应社会工作环境的重要环节&#xff0c;其重要性不言而喻。然而&#xff0c;传统的高校专业实习管理模式往往存在信息不对称、流程繁琐、效率低下、…

C# Blazor Server 调用海康H5Player播放摄像头画面

目标 调用海康综合安防平台api&#xff0c;通过摄像头的cameraIndexCode调用【获取监控点预览取流URLv2】api&#xff0c;得到websocket 的url&#xff0c;然后在blazor server中使用htplayer.js播放摄像头实时画面。 步骤 根据摄像头名字&#xff0c;调用【查询监控点列表v2…

CGAL Surface_Mesh 示例

CGAL Surface_Mesh 示例 创建一个简单的网格曲面Surface_Mesh对象&#xff0c;然后通过半边结构遍历某个面的顶点以及遍历整个网格对象的所有顶点&#xff0c;最后计算网格所有顶点的3D凸包网格。 项目 sm_points.cpp #include <CGAL/Simple_cartesian.h> #include &l…

Virtio半虚拟化基本原理简介

virtio半虚拟化基本原理简介 在本文中&#xff0c;将首先了解VirtIO的基本概念及其应用原因&#xff0c;然后从技术角度深入探讨VirtIO的关键领域&#xff0c;包括VirtIO设备与驱动程序、VirtQueues和VRings。在介绍完这些基础知识后&#xff0c;将通过一个在Qemu中的VirtIO设备…

【C++】函数模板,类模板,全特化,偏特化详解

目录 1. 函数模板 1.1 函数模板概念 1.2 函数模板格式 1.3 函数模板的原理 1.4 函数模板的实例化 1.4.1 隐式实例化 1.4.2 显示实例化 1.5 模板参数的匹配原则 2. 类模板 2.1 类模板的定义格式 2.2 类模板的实例化 3. 非类型模板参数 4. 模板的特化 4.1 类模板…

AI动漫转真人终极教程!3步做出爆款内容,音乐推广号变现

从小到大&#xff0c;我们看过的动漫、玩过的游戏有很多很多 但我们会发现里面的角色或者人物都是二次元的 我就会好奇这些动漫人物在现实中会长什么样 而现在&#xff0c;我们通过AI绘画竟然就能还原出来他们现实中的样子 除了动漫角色和游戏人物&#xff0c;古代的画像、…

flink设置保存点和恢复保存点

增加了hdfs package com.qyt;import org.apache.flink.api.java.functions.KeySelector; import org.apache.flink.api.java.tuple.Tuple2;import org.apache.flink.runtime.state.storage.FileSystemCheckpointStorage;import org.apache.flink.streaming.api.datastream.Dat…

C++友元和运算符重载

目录 一. 友元 friend 1.1 概念 1.2 友元函数 1.3 友元类 1.4 友元成员函数 二. 运算符重载 2.1 概念 2.2成员函数运算符重载 2.3 成员函数运算符重载 2.4 特殊运算符重载 2.4.1 赋值运算符重载 2.4.2 类型转换运算符重载 2.5 注意事项 三、std::string 字符串类…

什么是期望最大化算法?

一、期望最大化算法 期望最大化&#xff08;EM&#xff09;算法是一种在统计学和机器学习中广泛使用的迭代方法&#xff0c;它特别适用于含有隐变量的概率模型参数估计问题。在统计学和机器学习中&#xff0c;有很多不同的模型&#xff0c;例如高斯混合模型&#xff08;GMM&…