【发布时间】:2017-09-07 07:26:59
【问题描述】:
问题
我今天在算法课上遇到了这个问题:
给定函数
maxSubstring(s, t),其中s是一个字符串,t是s的一个子字符串,找出可以删除第一个或最后一个子字符串t的最大迭代次数。
概念
这是在 s = banababbaa 和 t = ba 上调用的函数 maxSubstring 的可视化。
b a n a b b a a
1st move: n a b a b b a or b a n a b a b a
2nd move: n a b b a a or n a b a b a n a b a b a or b a n a b a
3rd move: n a b a or n a b a n a b a or n a b a
4th move: n a n a
因此,此操作需要四步。
尝试
这是我对问题的解决方案。它可以工作,但是当我使用较大的字符串作为参数时它会很慢。
尝试 #1
function maxSubstring(s, t) {
if (s.includes(t)) {
var idxSubstr = s.replace(t, '');
var lastIdxSubstr = s.substr(0, s.lastIndexOf(t)) + s.substr(s.lastIndexOf(t) + t.length, s.length);
return 1 + Math.max(maxSubstring(idxSubstr, t), maxSubstring(lastIdxSubstr, t)));
}
return 0;
}
尝试 #2
function maxSubstring(s, t) {
if (s.includes(t)) {
var idx = s.indexOf(t), lastIdx = s.lastIndexOf(t);
var idxSubstr = s.substr(0, idx) + s.substr(idx + t.length, s.length);
var lastIdxSubstr = s.substr(0, lastIdx) + s.substr(lastIdx + t.length, s.length);
if (idx != lastIdx) {
return 1 + Math.max(maxSubstring(idxSubstr, t), maxSubstring(lastIdxSubstr, t));
} else {
return 1 + maxSubstring(idxSubstr, t);
}
}
return 0;
}
更新原因:通过将indexOf 和lastIndexOf 的值存储在变量中,效率略有变化。
尝试 #3
function maxSubstring(s, t) {
var idx = s.indexOf(t);
if (idx >= 0) {
var lastIdx = s.lastIndexOf(t);
var idxSubstr = s.substr(0, idx) + s.substr(idx + t.length);
if (idx != lastIdx) {
var lastIdxSubstr = s.substr(0, lastIdx) + s.substr(lastIdx + t.length);
return 1 + Math.max(maxSubstring(idxSubstr, t), maxSubstring(lastIdxSubstr, t));
} else {
return 1 + maxSubstring(idxSubstr, t);
}
}
return 0;
}
更新原因:减少了在检查第一个索引之前重新定义某些值并阻止 lastIndexOf 计算的实例。
回答要求
我可以使用任何算法或方法来优化此代码吗? Math.max 是罪魁祸首,所以如果有人知道如何完全避免使用这种方法,我将不胜感激。
换句话说,maxSubstring 只能在其自身内部调用一次,但Math.max 要求它被调用两次(一次用于子字符串的第一个索引,另一次用于该子字符串的最后一个索引)。
最后,您介意告诉我什么是大 O 表示法适用于我的解决方案,什么是大 O 表示法适用于您的解决方案吗?这不是最初挑战的一部分,但我自己很好奇。提前致谢。
【问题讨论】:
-
如果
Math.max只是你所担心的,那你为什么不使用<,>来比较,毕竟只有2个参数。使用三元运算符和比较运算符找到 2 之间的最大值。 -
这里概述了这个概念,但适用于 Java。它在我的函数的运行时并没有显示出很大的变化。 stackoverflow.com/questions/2103606/…
-
这不会产生很大的加速,但是你的 .includes() 和 .replace() 基本上做了两次在 s 中查找 t 的工作,所以你可以获得一点速度通过将它们组合起来。事实上,你的 lastIndexOf(t) 调用也在做同样昂贵的操作,所以可能只做一次而不是 4 次!
-
嗯。其他复杂性包括 indexOf 和 lastIndexOf,它们最终都是循环。
标签: javascript string algorithm optimization