zoukankan      html  css  js  c++  java
  • LeeCode(No3

    题目:

    Given a string, find the length of the longest substring without repeating characters.

    示例:
    
    Given "abcabcbb", the answer is "abc", which the length is 3.
    
    Given "bbbbb", the answer is "b", with the length of 1.
    
    Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

    问题的难点在于光标移动过程中,一旦遇到重复需要重新开始计算长度

    第一次提交的代码如下:

    class Solution {
        public int lengthOfLongestSubstring(String s) {
            int longestLength = 0;
            int currentLength = 0;
            String longestStr = "";
            char tmpChar;
            int repeatIndex = 0;
    
            for(int i = 0; i < s.length(); i++){
                tmpChar = s.charAt(i);
                repeatIndex = longestStr.indexOf(tmpChar, 0);
                // 遇到重复,从重复的下一位开始
                if(repeatIndex >= 0) {
                    if(longestLength < currentLength){
                        longestLength = currentLength;
                    }
                    longestStr = longestStr.substring(repeatIndex + 1) + tmpChar;
                    currentLength = longestStr.length();
                } else {
                    longestStr += s.charAt(i);
                    currentLength++;
                }
            }
    
            if(longestLength < currentLength) {
                return currentLength;
            }
    
            return longestLength;
        }
    }

    提交后执行效率只击败了15.65%

    为提高效率,考虑更新如下方面:

    1. String 用StringBuilder替换(不需要线程安全,所以不使用开销大的StringBuffer)

    2. char用String替换(是为了避免循环中char到String转换时的开销)

    修改后的代码如下:

    class Solution {
        public int lengthOfLongestSubstring(String s) {
            int longestLength = 0;
            int currentLength = 0;
            StringBuilder builder = new StringBuilder();
            String charStr;
            int repeatIndex;
    
            for(int i = 0; i < s.length(); i++){
                charStr = s.substring(i, i + 1);
                repeatIndex = builder.indexOf(charStr, 0);
                // 遇到重复,从重复的下一位开始
                if(repeatIndex >= 0) {
                    if(longestLength < currentLength){
                        longestLength = currentLength;
                    }
                    builder.delete(0, repeatIndex + 1);
                    builder.append(charStr);
                    currentLength = builder.length();
                } else {
                    builder.append(charStr);
                    currentLength++;
                }
            }
    
            if(longestLength < currentLength) {
                return currentLength;
            }
    
            return longestLength;
        }
    }

    提交后执行效率只击败了65.57%

    如何再进一步提高效率呢?因为循环里面有查询字符存在的功能,考虑替换数据结构,用HashMap替换StringBuffer,

    但是在思考了一会没有找到使用HashMap的写法,于是直接参考了现有的方案,如下:

    public class Solution {
        public int lengthOfLongestSubstring(String s) {
            int n = s.length(), ans = 0;
            Map<Character, Integer> map = new HashMap<>(); // current index of character
            // try to extend the range [i, j]
            for (int j = 0, i = 0; j < n; j++) {
                if (map.containsKey(s.charAt(j))) {
                    i = Math.max(map.get(s.charAt(j)), i);
                }
                ans = Math.max(ans, j - i + 1);
                map.put(s.charAt(j), j + 1);
            }
            return ans;
        }
    }

    其实实现的逻辑跟之前的思路一致,j 作为整个字符串的额游标,i 作为遇到重复元素后重新开始位置的游标,ans记录最大值

    这样的写法不但是用HashMap来代替String查找,而且不用单独存储子字符串。

    复杂度如下:

    Complexity Analysis

    • Time complexity : O(n)O(n). Index jj will iterate nn times.

    • Space complexity (HashMap) : O(min(m, n))

    参考:

    https://leetcode.com/problems/longest-substring-without-repeating-characters

    ---栖息之鹰(一个外表懒洋洋的内心有激情的程序员) 此博客为笔者原著,转载时请注明出处,谢谢!
  • 相关阅读:
    Adding iAds to Cocos2d-x on iOS
    让游戏支持复杂手势识别
    【ybtoj高效进阶 21285】独立生物(图论)(博弈论)(DP)
    【ybtoj高效进阶 21286】等差数列(数学)(分类讨论)
    【ybtoj高效进阶 21278】内需消费(线段树)(广义矩阵乘法)(DP)
    【ybtoj高效进阶 21277】逆序对数(数学)(DP)
    【ybtoj高效进阶 21274】相似序列(主席树)(哈希)(二分)
    【ybtoj高效进阶 21273】铲雪问题(树形DP)
    【ybtoj高效进阶 21272】生命游戏(bfs)(二分)
    【ybtoj高效进阶 21270】三只企鹅(树链剖分)(线段树)
  • 原文地址:https://www.cnblogs.com/roostinghawk/p/8177210.html
Copyright © 2011-2022 走看看