【发布时间】:2015-08-16 23:30:28
【问题描述】:
以下是来自名为 codility 的编码面试网站的演示问题:
字符串 S 的前缀是 S 的任何前导连续部分。例如,“c”和“cod”是字符串“codility”的前缀。为简单起见,我们要求前缀不为空。
字符串 S 的前缀 P 的乘积是 P 的出现次数乘以 P 的长度。更准确地说,如果前缀 P 由 K 个字符组成,并且 P 在 S 中恰好出现 T 次,则乘积等于 K * T.
例如,S = "abababa" 有以下前缀:
- “a”,其乘积等于 1 * 4 = 4,
- “ab”,其乘积等于 2 * 3 = 6,
- “aba”,其乘积等于 3 * 3 = 9,
- “abab”,其乘积等于 4 * 2 = 8,
- “ababa”,其乘积等于 5 * 2 = 10,
- “ababab”,其乘积等于 6 * 1 = 6,
- “abababa”,其乘积等于 7 * 1 = 7。
最长前缀与原始字符串相同。目标是选择使产品价值最大化的前缀。在上面的例子中,最大乘积是 10。
以下是我在 Java 中需要 O(N^2) 时间的糟糕解决方案。显然可以在 O(N) 中做到这一点。我在想 Kadanes 算法。但我想不出任何方法可以在每一步编码一些信息,让我找到运行的最大值。谁能想到一个 O(N) 算法呢?
import java.util.HashMap;
class Solution {
public int solution(String S) {
int N = S.length();
if(N<1 || N>300000){
System.out.println("Invalid length");
return(-1);
}
HashMap<String,Integer> prefixes = new HashMap<String,Integer>();
for(int i=0; i<N; i++){
String keystr = "";
for(int j=i; j>=0; j--) {
keystr += S.charAt(j);
if(!prefixes.containsKey(keystr))
prefixes.put(keystr,keystr.length());
else{
int newval = prefixes.get(keystr)+keystr.length();
if(newval > 1000000000)return 1000000000;
prefixes.put(keystr,newval);
}
}
}
int maax1 = 0;
for(int val : prefixes.values())
if(val>maax1)
maax1 = val;
return maax1;
}
}
【问题讨论】:
-
内循环(j)不应该按升序迭代吗?
-
我在这里猜测,但我认为,对于后缀的 O(1) 查询,倒置字符串(建立在 O(n) 时间上)的后缀树可能会在所需的范围内解决问题时间限制
-
Little Santi - 如果我们只是想找到最大的产品也没关系。我之所以这样,是因为我认为 o(n) 解决方案可能也会向后看。
-
您的解决方案不是 O(N^2)。它有两个 O(N) 嵌套循环,但在内部循环中有一个 O(N) containsKey(因为 keystr 有 O(N) 个字符,并假设一个 O(1) 哈希图)。所以算法实际上是O(N^3)。
-
复制了这个 2 岁的错误标题问题:stackoverflow.com/questions/20251645/…
标签: algorithm performance dynamic-programming kadanes-algorithm