【问题标题】:Is algorithm optimal and does it satisfy specified complexity?算法是否最优,是否满足指定的复杂性?
【发布时间】:2020-10-11 10:59:29
【问题描述】:

给定字符串的字符必须按照另一个模式字符串定义的顺序进行排序。 复杂度要求O(n + m) 其中n 的长度为字符串,m 是模式的长度。

例子:

模式:1234567890AaBbCcDdEeFfGgHh

字符串:dH7ee2D6a341Fb9Ea20dhC1g7ca32Ba2Gac5f76A2g

结果:112222233456677790AaaaaaBbCccDddEeeFfGggHh

Pattern 包含字符串的所有字符,每个字符只出现一次。

我的代码:

// Instances of possible values ​​for input:
String pattern = "1234567890AaBbCcDdEeFfGgHh";
String string = "dH7ee2D6a341Fb9Ea20dhC1g7ca32Ba2Gac5f76A2g";

// Builder to collect characters for sorted result:
StringBuilder result = new StringBuilder();

// Hash table based on characters from pattern to count occurrence of each character in string:
Map<Character, Integer> characterCount = new LinkedHashMap<>();

for (int i = 0; i < pattern.length(); i++) {
    // Put each character from pattern and initialize its counter with initial value of 0:
    characterCount.put(pattern.charAt(i), 0);
}

// Traverse string and increment counter at each occurrence of character
for (int i = 0; i < string.length(); i++) {
    char ch = string.charAt(i);
    Integer count = characterCount.get(ch);
    characterCount.put(ch, ++count);
}

// Traverse completed dictionary and collect sequentially all characters collected from string
for (Map.Entry<Character, Integer> entry : characterCount.entrySet()) {
    Integer count = entry.getValue();

    if (count > 0) {
        Character ch = entry.getKey();

        // Append each character as many times as it appeared in string
        for (int i = 0; i < count; i++) {
            result.append(ch);
        }
    }
}

// Get final result from builder
return result.toString();

这段代码是最优的吗?有没有办法改进这个算法?我是否正确理解它满足给定的复杂度 O(n + m)?

【问题讨论】:

  • 您使用的是 Java 吗?例如,如果将字符存储为可变长度 UTF-8,则 charAt() 将不是 O(1),而是 O(N)。 append() 同上,它可能必须发现数组的末尾。

标签: java string algorithm sorting time-complexity


【解决方案1】:

不确定你或我的时间是否更快。 但这里有一个替代方案:

import java.math.BigDecimal;
class Playground {
    public static void main(String[ ] args) {
        String pattern = "1234567890AaBbCcDdEeFfGgHh";
        String s = "dH7ee2D6a341Fb9Ea20dhC1g7ca32Ba2Gac5f76A2g";
        long startTime = System.nanoTime();
        StringBuilder sb = new StringBuilder();

        for (char c : pattern.toCharArray()) {
            sb.append(s.replaceAll("[^" + c + "]", ""));
        }

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

        BigDecimal  elapsedTime =
            new BigDecimal( String.valueOf(System.nanoTime() - startTime)
                          )
        .divide(
            new BigDecimal( String.valueOf(1_000_000_000)
                          )
        );
        System.out.println(elapsedTime + " seconds");
    }
}

解释:

对于模式中的每个字符,使用字符串的基于正则表达式的 replaceAll 方法将除当前字符之外的所有字符替换为空字符串。冲洗并重复。这将使您得到原始完整的每个字符的计数,按模式的字符序列排序。


输出:

112222233456677790AaaaaaBbCccDddEeeFfGggHh
0.021151652 seconds

(时间有点主观。它来自 Sololearn Java Playground。显然取决于他们服务器上的当前负载)

【讨论】:

  • @Emma 我也不确定。但我想我会把别的东西扔进锅里作为替代品。我也很想看看还有什么东西摆在桌面上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-11
  • 1970-01-01
相关资源
最近更新 更多