为什么这个算法这么慢?

时间:2016-11-15 20:36:23

标签: java algorithm

给定一个字符串,找到其中的第一个非重复字符并返回它的索引。如果它不存在,则返回-1。

s =“leetcode” 返回0。

s =“loveleetcode”, 返回2

这是我的解决方案,简单易懂。但是,在LeetCode上,它报告为“时间超出限制”,这意味着它太慢了。这是一个O(n ^ 2)解决方案。

public int firstUniqChar(String s) {

        if(s==null || s.isEmpty() ){
            return -1;
        }
        if(s.length()==1){
            return 0;
        }

        char[] ss = s.toCharArray();

        int size = s.length();
        HashSet<Character> repeats = new HashSet<Character>(); 
        for(int i=0; i<size; i++){

            for(int j=i+1; j<size; j++){
                if(repeats.contains(ss[i])){
                    continue;
                }
                if(ss[i]==ss[j]){
                    repeats.add(ss[i]);
                    break;
                }
            }

            if(!repeats.contains(ss[i])){
                return i;
            }
        }
        return -1;
    }

然而,另一个版本似乎更慢,不被判断为“时间超出限制”,如下所示:

static int firstUniqChar(String s) {

        if(s==null || s.isEmpty() ){
            return -1;
        }
        if(s.length()==1){
            return 0;
        }

        char[] ss = s.toCharArray();

        int size = s.length();
        for(int i=0; i<size; i++){

            boolean unique = true;
            for(int j=i+1; j<size; j++){
                if(ss[i]==ss[j]){
                    unique = false;
                    break;
                }
            }
            if(unique){
                for(int j=0; j<i; j++){
                    if(ss[i]==ss[j]){
                      unique = false;
                      break;
                    }
                }
            }
            if(unique){
                return i;
            }
        }
        return -1;
    }

2 个答案:

答案 0 :(得分:0)

不要做内循环。交易时间空间,并在您遍历字符串一次时跟踪哪些字符是唯一的。

public static int firstUniqChar(String s) {

    if(s==null || s.isEmpty() ){
        return -1;
    }
    if(s.length()==1){
        return 0;
    }


    Map<Character, Integer> uniqueCharacterMap = new LinkedHashMap<Character, Integer>();
    Set<Character> nonuniqueCharacterSet = new HashSet<Character>();

    for ( int i=0; i<s.length();i++) {
        Character c = s.charAt(i);
        if ( nonuniqueCharacterSet.contains(c) ) {
            // character has already been determined to repeat
        } else if ( uniqueCharacterMap.containsKey(c) ) { 
            uniqueCharacterMap.remove(c);  // It's not unique
            nonuniqueCharacterSet.add(c);
        } else {
            // so far, it is unique.
            uniqueCharacterMap.put(c, i);
        }
    }

    System.out.println(uniqueCharacterMap.toString());

    Iterator<Map.Entry<Character, Integer>> i = uniqueCharacterMap.entrySet().iterator();
    if ( i.hasNext() ) {
        Map.Entry<Character, Integer> e = i.next();
        return e.getValue();
    }

    return -1;
}

public static void main(String[] args) {
    System.out.println("firstUniqChar(leetcode) = " + firstUniqChar("leetcode"));
    System.out.println("firstUniqChar(loveleetcode) = " + firstUniqChar("loveleetcode"));
    System.out.println("firstUniqChar(aaabbbccc) = " + firstUniqChar("aaabbbccc"));

}

答案 1 :(得分:0)

一个简单的两遍(n)伪码算法(对于只包含字符范围&#39; a&#39;到&#39; z&#39;)的字符串可能类似于

CharFrequency = array [a..z] of integer
for c in InputString do
  inc(CharFrequency[c])
i = 0
while (i < Length(InputString)) and (CharFrequency[InputString[i]] <> 1) do
  inc(i)
if (i < Length(InputString))
  print(i)
else
  print(-1)