zoukankan      html  css  js  c++  java
  • [leetcode]Longest Substring Without Repeating Characters

    题目:

    Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.

    解题:

      首先想到是维护一个窗口,实现如下:

    int lengthOfLongestSubstring(string s) {
            int start = 0;
    		int lenOfLongest = 0;
    		int curLenOfLongest = 0;
    		int i;
    		int j;
    		int prev = 0;
    		map<char, int> window; //字符->在s中的索引
    		map<char, int>::iterator it;
    		window.clear();
    		for(i = 0; i < s.size(); i++){
    			it = window.find(s[i]);
    			if(it == window.end()){
    			//如果当前字符不在window中,则加入,
    				window[s[i]] = i;
    				curLenOfLongest = i - start + 1;
    			}else{
    			//如果当前字符在window中,
    			//则需要计算当前lenOfLongest,start后移到前一个s[i]的后一位,
    			//删除window中前一个s[i]和s[i]之前的字符
    			//...,start,...,prev,prev+1,...,i,...
    				prev = it->second;
    				curLenOfLongest = i - start;
    				for(j = start; j <= prev; j++){
    					window.erase(window.find(s[j]));
    				}
    				window[s[i]] = i;
    				start = prev + 1;
    			}
    			if(lenOfLongest < curLenOfLongest)lenOfLongest = curLenOfLongest;
    		}
    		return lenOfLongest;
        }
    

      这个算法通过了,但时间上惨不忍睹,124ms。

      从leetcode discuss里找到下面这样一个算法,号称5ms,他是传参char* 进去的,我改成string,提交之后17ms,表现不错。

         int lengthOfLongestSubstring(string s) {
    		int m[129] = {0};      //索引为0的元素不用
    		int i, j;
    		int cnt = 0, pre = 0;
    		int max = 0;
    		int c;
    
    		for (i = 0; c = s[i]; i++) {
    			if (pre < m[c]) {       //c已存在于当前子串中
    				if (max < cnt)
    					max = cnt;
    
    				cnt = i-m[c];
    				pre = m[c];
    			}
    
    			cnt++;
    			m[c] = i+1;
    		}
    		return max > cnt ? max : cnt;
    	}
    

      用下面这个算法来分析这种思路:

    int lengthOfLongestSubstring(string s) {
        int present[128] ;       // track positions of each characters
        std::fill_n(present, 128, -1); // invalidate all positions
        int start, len, max_len; // unique string tracking
        int i;
        for (start=0, len=0, max_len=0, i=0; i<s.size(); ++i) {
            int ch = (int) s[i];
            if ( present[ch] < 0 ||  // if new character OR
                 present[ch] < start) {  // character is not in the current unique string
                ++len;
            }
            else { // duplicated char
                len -= present[ch] - start; // adjust length
                start = present[ch] + 1;    // move forward one past dup. char
            }
            present[ch] = i;    // update char position
            if (max_len < len)
                max_len = len;
        }
        return max_len;
    }
    

      初始化一个128个元素的数组,代表acsii码表中前128个字符,每个元素的索引即代表字符,元素的值代表字符在字符串s中的位置,如present[97]=2代表‘a’字符在s的第3个位置。初始化的时候,每个元素的值都是-1。

      然后维护一个窗口,start代表着当前子串开始的位置(s中的位置),max_len表示当前获得的最大子串长度,len表示当前的子串长度。

      这个算法的时间复杂度是O(n)。

      再回过头来看第二个算法,它的思想跟第三个算法是一样的,pre记录子串开始的位置,cnt记录当前子串长度,max记录最大子串长度。

  • 相关阅读:
    web前端导出csv文件
    eclipseGUI的可视化开发工具插件
    ionic2程序调试
    rxjs简单入门
    ionic2中使用自定义图标
    解决 Ionic 浏览器跨域问题
    VS2017 Cordova Ionic2 移动开发-环境搭建
    ionic环境搭建
    TypeScript学习笔记 (一)基础特性
    localStorage使用总结
  • 原文地址:https://www.cnblogs.com/zhutianpeng/p/4291411.html
Copyright © 2011-2022 走看看