[LeetCode] Longest Substring Without Repeating Characters 最长无重复字符的子串 C++实现java实现...

最长无重复字符的子串

Given a string, find the length of the longest substring without repeating characters.

Example 1:

Input: "abcabcbb"
Output: 3 
Explanation: The answer is "abc", with the length of 3. 

Example 2:

Input: "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.

Example 3:

Input: "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

这道求最长无重复子串的题和之前那道 Isomorphic Strings 很类似,属于LeetCode的早期经典题目,博主认为是可以跟Two Sum媲美的一道题。给了我们一个字符串,让我们求最长的无重复字符的子串,注意这里是子串,不是子序列,所以必须是连续的。我们先不考虑代码怎么实现,如果给一个例子中的例子"abcabcbb",让你手动找无重复字符的子串,该怎么找。博主会一个字符一个字符的遍历,比如a,b,c,然后又出现了一个a,那么此时就应该去掉第一次出现的a,然后继续往后,又出现了一个b,则应该去掉一次出现的b,以此类推,最终发现最长的长度为3。所以说,我们需要记录之前出现过的字符,记录的方式有很多,最常见的是统计字符出现的个数,但是这道题字符出现的位置很重要,所以我们可以使用HashMap来建立字符和其出现位置之间的映射。进一步考虑,由于字符会重复出现,到底是保存所有出现的位置呢,还是只记录一个位置?我们之前手动推导的方法实际上是维护了一个滑动窗口,窗口内的都是没有重复的字符,我们需要尽可能的扩大窗口的大小。由于窗口在不停向右滑动,所以我们只关心每个字符最后出现的位置,并建立映射。窗口的右边界就是当前遍历到的字符的位置,为了求出窗口的大小,我们需要一个变量left来指向滑动窗口的左边界,这样,如果当前遍历到的字符从未出现过,那么直接扩大右边界,如果之前出现过,那么就分两种情况,在或不在滑动窗口内,如果不在滑动窗口内,那么就没事,当前字符可以加进来,如果在的话,就需要先在滑动窗口内去掉这个已经出现过的字符了,去掉的方法并不需要将左边界left一位一位向右遍历查找,由于我们的HashMap已经保存了该重复字符最后出现的位置,所以直接移动left指针就可以了。我们维护一个结果res,每次用出现过的窗口大小来更新结果res,就可以得到最终结果啦。

这里我们可以建立一个HashMap,建立每个字符和其最后出现位置之间的映射,然后我们需要定义两个变量res和left,其中res用来记录最长无重复子串的长度,left指向该无重复子串左边的起始位置的前一个,由于是前一个,所以初始化就是-1,然后我们遍历整个字符串,对于每一个遍历到的字符,如果该字符已经在HashMap中存在了,并且如果其映射值大于left的话,那么更新left为当前映射值。然后映射值更新为当前坐标i,这样保证了left始终为当前边界的前一个位置,然后计算窗口长度的时候,直接用i-left即可,用来更新结果res。

这里解释下程序中那个if条件语句中的两个条件m.count(s[i]) && m[s[i]] > left,因为一旦当前字符s[i]在HashMap已经存在映射,说明当前的字符已经出现过了,而若m[s[i]] > left 成立,说明之前出现过的字符在我们的窗口内,那么如果要加上当前这个重复的字符,就要移除之前的那个,所以我们让left赋值为m[s[i]],由于left是窗口左边界的前一个位置(这也是left初始化为-1的原因,因为窗口左边界是从0开始遍历的),所以相当于已经移除出滑动窗口了。举一个最简单的例子"aa",当i=0时,我们建立了a->0的映射,并且此时结果res更新为1,那么当i=1的时候,我们发现a在HashMap中,并且映射值0大于left的-1,所以此时left更新为0,映射对更新为a->1,那么此时i-left还为1,不用更新结果res,那么最终结果res还为1,正确,代码如下:

 

 最长无重复字符的子串C++ 实现解法一: 

复制代码
class Solution {
public:int lengthOfLongestSubstring(string s) {int res = 0, left = -1, n = s.size();unordered_map<int, int> m;for (int i = 0; i < n; ++i) {if (m.count(s[i]) && m[s[i]] > left) {left = m[s[i]];  }m[s[i]] = i;res = max(res, i - left);            }return res;}
};
复制代码

 

下面这种写法是上面解法的精简模式,这里我们可以建立一个256位大小的整型数组来代替HashMap,这样做的原因是ASCII表共能表示256个字符,但是由于键盘只能表示128个字符,所以用128也行,然后我们全部初始化为-1,这样的好处是我们就不用像之前的HashMap一样要查找当前字符是否存在映射对了,对于每一个遍历到的字符,我们直接用其在数组中的值来更新left,因为默认是-1,而left初始化也是-1,所以并不会产生错误,这样就省了if判断的步骤,其余思路都一样:

 

 最长无重复字符的子串C++ 实现解法二:

复制代码
class Solution {
public:int lengthOfLongestSubstring(string s) {vector<int> m(128, -1);int res = 0, left = -1;for (int i = 0; i < s.size(); ++i) {left = max(left, m[s[i]]);m[s[i]] = i;res = max(res, i - left);}return res;}
};
复制代码

 

 最长无重复字符的子串Java 解法二:

复制代码
public class Solution {public int lengthOfLongestSubstring(String s) {int[] m = new int[256];Arrays.fill(m, -1);int res = 0, left = -1;for (int i = 0; i < s.length(); ++i) {left = Math.max(left, m[s.charAt(i)]);m[s.charAt(i)] = i;res = Math.max(res, i - left);}return res;}
}
复制代码

 

下面这种解法使用了set,核心算法和上面的很类似,把出现过的字符都放入set中,遇到set中没有的字符就加入set中并更新结果res,如果遇到重复的,则从左边开始删字符,直到删到重复的字符停止:

 

 最长无重复字符的子串C++ 解法三:

复制代码
class Solution {
public:int lengthOfLongestSubstring(string s) {int res = 0, left = 0, i = 0, n = s.size();unordered_set<char> t;while (i < n) {if (!t.count(s[i])) {t.insert(s[i++]);res = max(res, (int)t.size());}  else {t.erase(s[left++]);}}return res;}
};
复制代码

 

 最长无重复字符的子串Java 解法三:

复制代码
public class Solution {public int lengthOfLongestSubstring(String s) {int res = 0, left = 0, right = 0;HashSet<Character> t = new HashSet<Character>();while (right < s.length()) {if (!t.contains(s.charAt(right))) {t.add(s.charAt(right++));res = Math.max(res, t.size());} else {t.remove(s.charAt(left++));}}return res;}
}
复制代码

 

转载于:https://www.cnblogs.com/suibian1/p/10947196.html

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

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

相关文章

使用自动机的Lucene新的邻近查询

最简单的Apache Lucene查询TermQuery匹配包含指定术语的任何文档&#xff0c;无论该术语出现在每个文档中的何处 。 使用BooleanQuery可以将多个TermQuery组合在一起&#xff0c;并完全控制哪些术语是可选的&#xff08; SHOULD &#xff09;和哪些是必需的&#xff08; MUST &…

关于HTML的面试题-html4/css2篇

1. 什么是HTML&#xff1f;2. 用过什么调试器&#xff08;浏览器&#xff09;&#xff0c;编辑器&#xff1f;3. HTML4.0 和 HTML5.0 的区别&#xff1f;4. 手写 HTML 代码5. 元素类型有哪些&#xff08;display有哪些属性&#xff09;&#xff1f;块元素、行元素和行内块元素的…

Java EE:异步构造和功能

介绍 Java EE具有许多API和构造以支持异步执行。 从可伸缩性和性能的角度来看&#xff0c;这是至关重要的。 让我们假设2个模块相互交互。 当模块A &#xff08;发送方&#xff09;以同步方式向模块B &#xff08;接收方&#xff09;发送消息时&#xff0c;通信将在单个线程的…

用 JA Transmenu 模块做多级弹出菜单

转自http://www.joomlagate.com “弹出菜单”这个说法本来不规范&#xff0c;尽管你我都明白这是什么意思&#xff0c;而实际上我们所理解的那个菜单样式英文说法是“Slide Menu”&#xff08;滑动菜单&#xff09;&#xff0c;如果要用“弹出菜单”就成了“Popup Menu”。当然…

关于HTML的面试题-html5/css3篇

1. html5 新增标签有哪些&#xff08;或者新增的语义标签&#xff09;&#xff1f;2. HTML5 中有哪些新特性&#xff1f;3. 视频有哪几种格式&#xff1f;这几种格式有什么区别&#xff1f;4. 写出你知道的层级选择符&#xff08;结构性伪类选择器&#xff09;5. 什么是渐进增强…

Elasticsearch的用例:灵活的查询缓存

在前两篇有关Elasticsearch用例的文章中&#xff0c;我们已经看到Elasticsearch 可用于存储甚至大量文档 &#xff0c;并且我们可以通过Query DSL使用Lucene的全文功能访问那些 文档 。 在这篇较短的文章中&#xff0c;我们将把两个用例放在一起&#xff0c;以了解读取繁重的应…

Vue底层架构及其应用(上)转

https://mp.weixin.qq.com/s?__bizMzIzNjcwNzA2Mw&mid2247486427&idx1&sn61f9579bbe1dfe26da4b53eb538fee13&chksme8d28643dfa50f557c56ce8b5bc9b0597a157a20791e21b1812fe2a30ff4cf2c813608473b43&mpshare1&scene23&srcid#rd 一、前言 市面上有很…

jquery笔记一:下载安装、语法、选择器、遍历选择元素的方法、jQuery动画

目前 jQuery 兼容于所有主流浏览器, 包括 IE 6&#xff01;开发时常用 jquery.js&#xff0c;上线用 jquery.min.js。 jq插件 目前jQuery有三个大版本&#xff1a; &#xff08;1&#xff09;1.x.x: 兼容ie6,7,8&#xff0c;使用最为广泛&#xff0c;官网只做BUG维护&#xff…

jquery简介 each遍历 prop attr

一、JQ简介 jQuery是一个快速、简洁的JavaScript框架&#xff0c;它封装了JavaScript常用的功能代码&#xff0c;提供一种简便的JavaScript设计模式&#xff0c;优化HTML文档操作、事件处理、动画设计和Ajax交互。 装载的先后次序&#xff1a;  jQuery封装库在上&#xff0…

如何让Visitor变得可爱1

本文转自&#xff1a;http://www.cnblogs.com/idior/archive/2005/01/19/94280.html 在wayfarer的文章中提到了如何利用visitor模式实现添加新的功能。如他所说&#xff0c;在实际过程中显的不是那么可爱。不过他为我们提供了一个可行的解决方案&#xff0c;本文将在此基础上使…

EJB 3.x:生命周期和并发模型(第1部分)

Java EE组件生命周期和与并发相关的详细信息对于经验丰富的专业人员而言可能不是新知识&#xff0c;但是对于初学者而言&#xff0c;这可能需要花费一些时间。 就EJB而言&#xff0c;了解其生命周期 &#xff08;以及相关的并发场景&#xff09;对于确保使用EJB的正确用法和解…

单独使用 laydate 日期时间组件

layui 日期和时间组件官方文档 需要注意几点&#xff1a; 下载压缩包后&#xff0c;复制整个 laydate 文件夹放到项目中&#xff0c;里面的文件不要改动位置&#xff0c;否则会报错&#xff1b;在移动端使用时&#xff0c;要给 input 添加 readonly 属性&#xff0c;否则点击…

从零开始学习SVG

1 什么是SVG&#xff1f; MDN中的定义是&#xff1a;SVG即可缩放矢量图形&#xff08;Scalable Vector Graphics&#xff0c;SVG)&#xff0c;是一种用来描述二维矢量图形的 XML 标记语言。 简单地说&#xff0c;SVG 面向图形&#xff0c;HTML 面向文本。SVG 与 Flash 类似&am…

layui 关于layDate设置时间限制问题

前面是尝试结果&#xff0c;有兴趣的可以康康&#xff0c;赶时间的可以直接翻到底下 ----->直达车 因为只有一个页面&#xff0c;没什么标准&#xff0c;所以自己就使用了layui的时间控件&#xff0c;并且作为独立组件。 第一次尝试 - 使用 min 一开始只想让结束时间有个…

QQ聊天记录快速迁移

QQ聊天记录快速迁移 在工作中大家经常会用到QQ来沟通&#xff0c;但是很多时候在其它设备上登录QQ就无法查看到之前的聊天记录和图片&#xff0c;这是因为电脑上的QQ聊天记录一般都是保存在电脑本地硬盘里&#xff0c;所以我们在换设备登录QQ后&#xff0c;是无法查看到之前电脑…

Hawtio和Jolokia的休眠统计

企业Java的很大一部分处理数据。 在企业设置中使用数据的所有不同方式中&#xff0c;仍然存在使用任何种类的O / R映射的行之有效且广泛教授的方法。 JPA标准使每个人都可以轻松使用它&#xff0c;并且它也应该是可移植的。 但是&#xff0c;我们不要谈论迁移细节。 O / R映射的…

laydate 时间控件去掉秒以及解决在移动端不能滑动的问题

一、时间控件去掉秒&#xff0c;保留时分 二、时间控件在移动端不能滚动 一、时间控件去掉秒&#xff0c;保留时分 方法一&#xff1a;使用 ready 回调函数 ready 控件在打开时触发。打开控件时让秒消失。 <script> laydate.render({elem: #endTime, //指定元素trigg…

Entity Framework Code First属性映射约定 转载https://www.cnblogs.com/libingql/p/3352058.html

Entity Framework Code First属性映射约定 Entity Framework Code First与数据表之间的映射方式有两种实现&#xff1a;Data Annotation和Fluent API。本文中采用创建Product类为例来说明tity Framework Code First属性映射约定的具体方式。 1. 表名及所有者 在默认约定的情况下…

layui 时间控件二次渲染,点击一个自定义按钮清空/重置时间控件

标题小标题一、错误尝试二、时间控件二次渲染的3种方法2.1 直接删除原来绑定时间控件的DOM&#xff0c;再重新渲染&#xff08;推荐&#xff09;&#xff1b;2.2 使用 clone() &#xff0c;并且改变 lay-key&#xff1b;2.3 使用 clone() &#xff0c;并且删除 lay-key&#xf…

2019年春第二次课程设计实验报告

一、试验项目名 贪吃蛇 二、试验功能介绍 通过数组构造小蛇&#xff0c;在通过数组中的变化控制小蛇移动和变长。 三、项目模块结构介绍 构造小蛇 小蛇移动 移动中碰到边框或自己失败 小蛇长大 四、实现界面展示 五、代码托管链接https://gitee.com/t001023/software_class_1_t…