我正在处理HackerRank上的一些挑战,并且在使功能更快/更高效以使其在提交过程中不会超时方面遇到一些麻烦。对于很大的输入(例如,字符串长度为1000或更多),通常会超时,而我使用的循环次数使函数正常工作。我知道循环使复杂度为0(n * n)或0(n * n * n)。我理解为什么由于上述复杂性问题而导致函数超时,但是我不确定如何使函数更有效以处理更大的输入。我是一名自学成才的编码员,因此请彻底,简单地解释所有答案,以便我学习。谢谢!
这是一个示例问题:
如果满足以下两个条件之一,则将字符串称为特殊回文字符串:
所有字符都相同,例如aaa。
除中间字符外的所有字符都相同,例如阿达阿(acdca不会满足此规则,但aadaa会满足)
特殊回文子串是指满足这些条件之一的任何子串。给定一个字符串,确定可以从中形成多少个特殊回文子字符串。
例如,给定字符串s = mnonopoo,我们有以下特殊回文子字符串:
功能说明
在下面的编辑器中完成substrCount函数。它应该返回一个整数,该整数表示可以从给定字符串形成的特殊回文子字符串的数量。 substrCount具有以下参数:
function substrCount(n, s) {
//if each letter is its own palindrome then can start with length for count
let count = n;
//space used to get the right string slices
let space = 1;
//so we only get full strings with the split and no duplicates
let numberToCount = n;
for(let i = 0; i < n; i++){
for(let j = 0; j < n; j++){
//slice the string into the different sections for testing if palindrome
let str = s.slice(j, j+space);
if(numberToCount > 0){
//if it is an even length the all characters must be the same
if(str.length % 2 === 0){
let split = str.split('');
let matches = 0;
for(let k = 0; k < split.length; k++){
if(split[k] === split[k+1]){
matches++;
}
}
if(matches === split.length -1){
count++;
}
//if it is not even then we must check that all characters on either side
//of the middle are all the same
} else {
if(str.length > 1){
let splitMid = Math.floor(str.length / 2);
let firstHalf = str.slice(0, splitMid);
let lastHalf = str.slice(splitMid+1, str.length);
if(firstHalf === lastHalf){
if(str.length === 3){
count++;
} else {
let sNew = firstHalf + lastHalf;
let split = sNew.split('');
let matches = 0;
for(let k = 0; k < split.length; k++){
if(split[k] === split[k+1]){
matches++;
}
}
if(matches === split.length -1){
count++;
}
}
}
}
}
}
numberToCount--;
}
numberToCount = n-space;
space++;
}
return count;
}
答案 0 :(得分:0)
我想出了一个我认为在性能上不太复杂的解决方案(一次循环和一次递归)
步骤
请告诉我这是否是正确的解决方案,否则我们可以加快速度
const stirng = "mnonopoo";
const str = stirng.split("");
let finalArray = [];
str.forEach((x, index) => {
if (str[index] === str[index + 1]) {
checkEven(str, index, 1)
}
if (str[index - 1] === str[index + 1]) {
checkOdd(str, index, 0)
}
finalArray.push(x);
})
function checkOdd(str1, index, counter) {
if (str1[index - counter] === str1[index + counter]) {
counter++;
checkOdd(str1, index, counter);
} else {
pushUnique(finalArray, str1.slice(index - counter + 1, index + counter).join(""));
return str1.slice(index - counter, index + counter).join("")
}
}
function checkEven(str1, index, counter) {
if (str1[index] === str1[index + counter]) {
counter++;
checkEven(str1, index, counter);
} else {
pushUnique(finalArray, str1.slice(index, index + counter).join(""));
return;
}
}
function pushUnique(array, value) {
if (array.indexOf(value) === -1) {
array.push(value);
}
}
console.log(finalArray)
答案 1 :(得分:-1)
由于您只寻找特殊回文,而不是所有回文,这使得降低复杂性要容易一些,但是即使那样,仍然会有一些特殊情况,例如“ abababababababa ....”。我看不出有什么办法可以降低它的复杂性。
我会这样处理。首先将所有重复数字分组。我不确定做到这一点的最佳方法,但是我在想也许要创建一个对象数组,其对象属性为count和letter。
从totalCount为0开始。
然后,选择所有计数为1的对象,并检查它们左右的对象,如果它们具有相同的字母值,则取MAX计数,并将该值+ 1加到totalCount( +1是指单个字母本身)。如果两边的字母值都不匹配,只需加1(以单独计算字母)即可。
可以处理所有奇数回文。现在要处理偶数回文。
选择所有计数大于1的对象,并获取它们的计数值,并将1计数中的序列添加到totalCount。此公式为(count / 2)*(1 + count)。 例: 在字符串中,您需要运行4A。有特殊回文(a,a,a,a,aa,aa,aa,aaa,aaa,aaaaa),总共有10个。(4/2)*(1 + 4)= 10。 / p>
我不知道这将减少您的处理时间,但是我认为它应该减少一些处理时间。