博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Leetcode: Longest Substring with At Most Two Distinct Characters
阅读量:7080 次
发布时间:2019-06-28

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

Given a string, find the length of the longest substring T that contains at most 2 distinct characters.For example, Given s = “eceba”,T is "ece" which its length is 3.

方法一:用HashMap, map里面存元素及其出现次数。维护一个最大长度。用两个指针,右指针一直走到出现3个dinstinct character为止。然后调整左指针删元素,直接从左往右逐个字符的删除,一直删到某个字符不会再出现。判断字符被删光就看次数是否减为了0.

 

采用方法:

1 public class Solution { 2     public int lengthOfLongestSubstringTwoDistinct(String s) { 3         if (s==null || s.length()==0) return 0; 4         HashMap
map = new HashMap
(); 5 int longest = 0; 6 int l = 0; 7 int r = 0; 8 while (r < s.length()) { 9 char c = s.charAt(r);10 if (map.containsKey(c)) {11 map.put(c, map.get(c)+1);12 }13 else {14 map.put(c, 1);15 if (map.size() >= 3) {16 longest = Math.max(longest, r-l); 18 while (map.size() >= 3 && l <= r) {
char d = s.charAt(l);19 if (map.get(d) > 1) map.put(d, map.get(d)-1);20 else map.remove(d);21 l++;22 }23 }24 }25 r++;26 }27 longest = Math.max(longest, r-l);28 return longest;29 }30 }

这里每个元素都会进入窗口一次,最多出窗口一次,所以平摊在每个元素上的时间复杂度是O(1),总时间复杂度为O(N)

网上另一种做法,可以删的更快。

转:

这题的线性解法是维护一个sliding window,里面的子字符串只含最多两个不同字符。当要添加一个新字符时,需要完全去掉之前的某一个字符的所有出现。这里有两个问题需要考虑:

1)在已有的两个字符中,如何选择该去掉其所有出现的字符?

2)在选定该去掉的字符后,如何改调整窗口?

对于问题1,窗口起始处的字符是一定会被去掉的,但是否总是应该选择这个字符然后去掉其所有出现么?以“abac”为例,可以发现当扫描到c时,a是一定会被去掉的,但是如果去掉所有出现过的a,那么最后只剩下"c"了。这时应该是去掉所有出现的b,顺便去掉了最开始的a,从而得到"ac"。由此观之,选择标准应该是字符的最后出现的位置,最后出现的位置越左(早),则其出现被全部删除后所减小的长度越少。因此,应该删光最后出现位置在最左的字符。

对于问题2,由于题目规定了窗口里最多只会有2种字符,其实怎么删都可以:慢点的可以从左到右逐个删除,快点的可以直接让新窗口以所选字符的最后出现位置的下一个字符打头。

以下代码用了一个Map结构来表示sliding window,key为字符,value为对应的最后出现位置。其实也可以完全避免使用Map,因为里面的entry最多只有两个,比较浪费空间。这里是考虑到了后来的扩展以及代码的维护。

这里为了获得Map的最后位置最早出现的字符,遍历了所有的entry。这其实是非常低效的,但考虑到Map里实际只有2个元素,所以遍历的开销也很小,可以忽略不计。

1     public int lengthOfLongestSubstringTwoDistinct(String s) { 2         int start = 0; 3         int maxLen = 0; 4  5         // Key: letter; value: the index of the last occurrence. 6         Map
map = new HashMap
(); 7 int i; 8 for (i = 0; i < s.length(); ++i) { 9 char c = s.charAt(i);10 if (map.size() == 2 && !map.containsKey(c)) {11 // Pick the character with the leftmost last occurrence.12 char charEndsMostLeft = ' ';13 int minLast = s.length();14 for (char ch : map.keySet()) {15 int last = map.get(ch);16 if (last < minLast) {17 minLast = last;18 charEndsMostLeft = ch;19 }20 }21 22 map.remove(charEndsMostLeft);23 start = minLast + 1;24 }25 map.put(c, i);26 maxLen = Math.max(maxLen, i - start + 1);27 }28 return maxLen;29 }

 

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

你可能感兴趣的文章
有赞业务对账平台的探索与实践
查看>>
【Java基本功】一文读懂String及其包装类的实现原理
查看>>
leetcode讲解--824. Goat Latin
查看>>
深入解析Node.js中的Async和Await函数
查看>>
Ubuntu 下如何安装与卸载软件 ( 一 :GUI版)
查看>>
07_01_定义加载器(Webpack Book)
查看>>
Let's encrypt 通配域名DNS验证方式的证书自动更新
查看>>
PHP 框架学习(二):Laravel
查看>>
总结常见的违背Rest原则的接口设计做法
查看>>
JAVASCRIPT中THIS指的是什么?
查看>>
推荐一个全新的简单可扩展的基于MVC模式开发的PHP CMS系统:metacms
查看>>
基于 Laravel 的模块化开发框架
查看>>
将Medium中的博客导出成markdown
查看>>
D-Bus Tutorial
查看>>
Spring中的事务控制
查看>>
Promise的简单实现
查看>>
我的豆瓣短评爬虫的多线程改写
查看>>
netfilter 结构整理
查看>>
Golang TcpProxy和Nodejs TcpProxy
查看>>
『总结』jQuery常用函数方法
查看>>