leetcode之路003 Longest Substring Without Repeating Characters
来源:互联网 发布:电子笔记 知乎 编辑:程序博客网 时间:2024/06/05 14:07
题目大意:很好理解,求最长的没有重复元素的子串的长度,例如:“abcabcbb”结果是abc,长度3,“bbbbb”结果时b,长度1.
思路:用hash_map做的,因为每次找下一个字符时,都需要从前面的子串中进行查找操作,利用hash_map达到快速查找。因为不需要要排序操作,因此程序中是用的unordered_map。
1.令最长的无重复子串长度为max,i从0循环到字符串长度减去max
2.对每一个循环,从i开始,指定一个数len来指示从i开始能达到的长度,若从unordered_map hash中没有发现字符s[i],则将s[i]加入hash中,并将len++指向下一个字符,再进行判断是否在unordered_map hash中,依次循环执行。直到从unordered_map hash中找到此字符,即重复了。此时len即为从i开始的最大长度。
3.判断2找到的len与max的大小,若len大于max,则更新max。
4.按照最简单的思路,用1-3,一直循环,肯定能求出最大的max。但是,效率是个问题,提交时肯定会出现超时,有一个测试数据,string长度大于31000。在每一次i的循环中,在找到重复元素时,我进行了如下优化:
a.找到hash中那个重复元素的下标,若此下标大于i值,则将此下标值+1赋给i。例:"abcdecmnp",此时c重复,则hash中c的下标为2,大于第一个a的下标0,将i=2+1,因为从0-2的元素开始的子串长度必定小于从a开始的长度。
b.找到hash中那个重复元素的下标,若此下标等于i值,则继续判断下一个元素是否重复。例:“abcdabmn”,i=0,到a重复时,找到的重复下标为0,判断下一个元素b,直到没有发现重复或者进入a中。
优化的策略有点混乱,自己举例测试出来进行尝试的结果,感觉不是很好,还可以优化。提交运行ac了,运行时间为76ms,发现提交的c++代码一般都在16-30ms之间= =。代码如下:
#include<iostream>#include<string>#include <unordered_map>using namespace std;class Solution{public:int lengthOfLongestSubstring(string s){int max=0,len=0;int off=0;for(int i=0;i<s.length()-max;++i){unordered_map<char,int> hash;unordered_map<char,int>::iterator hashit;len=0;while(hash.find(s[i+len])==hash.end()&&(i+len)<s.length()){hash[s[i+len]]=len++;}if(len>max) max=len;off=0;if(hash.find(s[i+len+off])!=hash.end()){while(hash.find(s[i+len+off])!=hash.end()){hashit=hash.find(s[i+len+off]);if(hashit->second>off){ off=hashit->second+1; break;}else ++off;}--off;}i=i+off;}return max;}};int main(){string ss="aab";Solution so;int rr=so.lengthOfLongestSubstring(ss);cout<<rr<<endl;return 0;}本来想改进一下代码的,结果毫无头绪。看了讨论区的算法思想,写了以下代码:
class Solution{public:int lengthOfLongestSubstring(string s) {unordered_map<char,int> hash;unordered_map<char,int>::iterator hashit; int longest=0,m=0; for (int i=0;i<s.length();++i) { if(hash.find(s[i])!=hash.end()) {hashit=hash.find(s[i]);m=max(m,hashit->second+1); } <span style="white-space:pre"></span>hash[s[i]]=i; longest=max(longest,i-m+1); } return longest;}};主要思路也是利用hash_map的快速查找,在hash中找到重复元素后,根据重复元素的下标和原子串的第一个位置下标相比,来更新m的值,已达到更新最长长度longest值的目的。此算法只需要O(n)的时间。并且,只用了一个hash_map就可以完成操作,因为如果“abcacdeb“,比如b值,前面已经存到hash_map中了,但是,此时m值指示的是子串的起始位置为3,因此即使可以找到,但是不会影响长度的计算。
反观自己写的,对每一个i需要进行一个循环,还需要分配hash_map,直到找到重复时才停止循环,虽然有优化可以使i值进行跳跃,不处理长度肯定小于max的情况,但总的说来,复杂了许多。从提交的运行时间,上述代码只需56ms,自己的需要76ms。
2016.09.02更新 JAVA代码
public class Solution { public int lengthOfLongestSubstring(String s) {if (s == null || s.length() == 0) {return 0;}int res = 1;Queue<Character> q = new LinkedList<>();q.offer(s.charAt(0));Map<Character, Integer> map = new HashMap<>();map.put(s.charAt(0), 0);for (int i = 1; i < s.length(); i++) {if (map.containsKey(s.charAt(i))) {res = Math.max(res, i - map.get(s.charAt(i)));while (!q.isEmpty() && q.peek() != s.charAt(i)) {map.remove(q.poll());}q.poll();map.put(s.charAt(i), i);q.offer(s.charAt(i));} else {map.put(s.charAt(i), i);q.offer(s.charAt(i));res = Math.max(res, map.size());}}return res;}}
优化,只用一个map:
public int lengthOfLongestSubstring(String s) {if (s == null || s.length() == 0) {return 0;}int res = 1;Map<Character, Integer> map = new HashMap<>();int low = -1;for(int i = 0; i < s.length(); i++) { if(map.containsKey(s.charAt(i))) { low = Math.max(low, map.get(s.charAt(i))); map.put(s.charAt(i), i); } else { map.put(s.charAt(i), i); } res = Math.max(res, i - low);}return res;}
- leetcode之路003 Longest Substring Without Repeating Characters
- leetcode之Longest Substring Without Repeating Characters
- LeetCode之Longest Substring Without Repeating Characters
- LeetCode 之 Longest Substring Without Repeating Characters
- leetcode之Longest Substring Without Repeating Characters
- leetcode之 Longest Substring Without Repeating Characters
- Leetcode 之 Longest Substring Without Repeating Characters
- leetcode 之Longest Substring Without Repeating Characters
- leetcode之Longest Substring Without Repeating Characters
- leetcode之Longest Substring Without Repeating Characters
- LeetCode之Longest Substring Without Repeating Characters
- LeetCode之Longest Substring Without Repeating Characters
- 【Leetcode】之Longest Substring Without Repeating Characters
- LeetCode之Longest Substring Without Repeating Characters
- leetcode之Longest Substring Without Repeating Characters
- LeetCode之Longest Substring Without Repeating Characters
- leetcode之 Longest Substring Without Repeating Characters
- LeetCode之Longest Substring Without Repeating Characters
- 关于const char *p 、char const*p 、char *const p 的区别
- TS流
- msh格式解析
- 测试
- Algorithms—31.Next Permutation
- leetcode之路003 Longest Substring Without Repeating Characters
- 客户端传值到服务器中文乱码
- 该 App 的 Info.plist 不能包含阻碍在任何 iOS 设备上打开此 App 的 UIRequiredDeviceCapabilities 键值
- 解决Picasso加载图片出现闪烁的问题
- #笔记#圣思园 JavaWeb 第59讲——使用Firebug调试JS、JSUnit,XUnit
- 关于C语言中的预处理指令
- Objective-C NSNotificationCenter (通知)的使用方法
- Android 适配问题
- 从零开始搭建hadoop分布式集群环境:(五)hadoop完全分布式集群环境配置