• [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记录最大子串长度。

  • 相关阅读:
    js中如何在不影响既有事件监听的前提下新增监听器
    史上最走心webpack4.0中级教程——配置之外你应该知道的事
    webpack4.0各个击破(10)—— Integration篇
    webpack4.0各个击破(9)—— karma篇
    webpack4.0各个击破(8)—— tapable篇
    webpack4.0各个击破(7)—— plugin篇
    MYSQL的安装
    数据库的分类
    python接口调用把执行结果追加到测试用例中
    python分布式接口,参数化实战二
  • 原文地址:https://www.cnblogs.com/zhutianpeng/p/4291411.html
Copyright © 2020-2023  润新知