博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
算法题解:从输入string中找出无重复字符的最长子串
阅读量:5815 次
发布时间:2019-06-18

本文共 1477 字,大约阅读时间需要 4 分钟。

题目分析

题目链接:

这道题目主要难点在于这样一个问题:

a, b, c, d, e, f, c, g, h, ...
我从第一个字符开始检查,已经检查到f了,目前为止还没有出现重复字符:
[a, b, c, d, e, f,] c, g, h, ...
检查到下一个c时,发现它在前面已经出现过了(至于如何判断新字符是否已经出现过,我们在下面讨论):
[a, b, c, d, e, f, c,] g, h, ...
这时应该怎么办?下一次检查哪个子串?
这时将子串的右端点右移是错误的,因为这样子串中依然包括两个c
[a, b, c, d, e, f, c, g,] h, ...
正确的方式是将子串左端点右移,使它不包含两个成重复的字符:
a, b, c, [d, e, f, c,] g, h, ...
然后再将右端点右移,继续检查:
a, b, c, [d, e, f, c, g,] h, ...

那么如何判断新字符是否已经在子串中出现过呢?

我们可以使用Map<char, bool>,它的原理是:将每个字符作为一个节点存在一颗二叉树中,尝试插入新字符的节点,如果出现冲突(树中已经有相同字符的节点),则表明新字符已经出现过。每次判断的复杂度为log(m),m为子串的最大长度。在进行子串左端点右移的时候,要记得将被移出的字符从map种删掉。
还有一种更高效的查找方法:哈希表。在这道题使用哈希表有天然的优势:char的范围是已知的、
较小的——[0, 255](unsigned char)。那么就可以直接用一个bool[256]数组来存储每一种字符是否已出现。在进行子串左端点右移的时候,要记得将被移出的字符重新标记为未访问。

以上两种方法在进行子串左端点右移的时候都要进行重置操作,为了避免它,我们不存储bool(是否出现过),而是存储int(上次出现的下标)。详见下面的代码部分。

代码

class Solution {public:    int lengthOfLongestSubstring(string s) {        map
last_appear_index; int sub_string_start = 0, max_length = 0; map
::iterator it; for (int i = 0; i < s.length(); i++) { it = last_appear_index.find(s[i]); if (it != last_appear_index.end() && it->second >= sub_string_start) { sub_string_start = it->second+1; } last_appear_index[s[i]] = i; max_length = max(max_length, i-sub_string_start+1); } return max_length; }};

虽然使用bool[256]更加高效,但是作为算法题,不应该对用户可能输入的字符做任何猜测(在其他语言中,字符可能不用整数表示),使用map<char, int>是更通用的方法。

转载地址:http://fdqbx.baihongyu.com/

你可能感兴趣的文章
在字符串中找出第一个只出现一次的字符
查看>>
tomcat中无法创建tomcat6或者7的解决办法
查看>>
Spring项目MySQL向MariaDB的迁移
查看>>
《Linux企业应用案例精解(第2版)》新书发布
查看>>
虚基类
查看>>
微信小程序周报(第三期)
查看>>
数据[BQTY tarPosm]
查看>>
SAE Tornado Worker 的一点使用经历
查看>>
构建部署脚本
查看>>
排序算法 总结
查看>>
进程与系统调用
查看>>
深入理解HTTP Session
查看>>
一个十年没更新的项目还有没有必要玩
查看>>
Spring Boot 2.0(六):使用 Docker 部署 Spring Boot 开源软件云收藏
查看>>
MySQL高可用架构之MHA
查看>>
PlayScala实战 - 如何优雅地取出多层Future中的结果?
查看>>
Play For Scala 开发指南 - 第3章 常用类介绍
查看>>
Android开发效率—Eclipse快捷键
查看>>
iOS添加黑色蒙层
查看>>
Hibernate遇到的问题与解决方案
查看>>