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

  • 相关阅读:
    [HDU2866] Special Prime (数论,公式)
    [骗分大法好] 信息学竞赛 骗分导论(论文搬运)
    flayway数据库管理
    RabbitMQ的基本概念与原理
    springboot+ideal实现远程调试
    盘点总结
    mysql查看进程命令
    Java字符串正则文本替换
    springboot代码级全局敏感信息加解密和脱敏方案
    使用PMD进行代码审查
  • 原文地址:https://www.cnblogs.com/zhutianpeng/p/4291411.html
Copyright © 2011-2022 走看看