【问题标题】:Codewars challenge - Longest vowel substringCodewars 挑战 - 最长元音子串
【发布时间】:2017-11-22 11:03:19
【问题描述】:

是的,我正在经历一个代码战争挑战,其目的是返回最长元音子串的长度,因为在“codewarriors”中将是“io”,所以答案是 2。我解决的方式它是通过用空格替换非元音,将剩下的元音分成一个数组,然后循环这个数组并将第一个子字符串推入另一个数组,然后我设置另一个 for 循环,这样我就可以循环第一个数组使用第二个数组检查长度,并在必要时替换为最长的。

这是我遇到麻烦的地方,因为我正在推送第一个值(与其他值进行比较的值),但如果在第二个循环中需要替换它,我只是替换不推送的值,所以如果第一个值是最长的数组将是一个对象,如果需要在第二个循环中替换它,它将被替换但它会变成一个字符串,这意味着给出长度的结束返回语句将需要更改在最长.length 和最长 [0].length 之间,我通过在末尾添加条件检查 typeof 来解决它,但我想知道是否有另一种解决方法?

我是初学者,如果上述内容有点混乱,请原谅我,非常欢迎任何关于其他解决挑战的方法的提示。

这是行不通的代码 -

  function longestVowel(str) {

  var seperateVowels = str.replace(/[bcdfghjklmnpqrstvwxyz]/ig, ' ');

  var split = seperateVowels.split(" ");

  var longest = [];
  for(var i = 0; i < split.length; i++) {
    if(longest.length === 0 && split[i] != "") {
      longest = split[i];
    }  for(var j = 0; j < longest.length; j++) {
      if(split[i].length > longest[j].length) {
        longest = split[i];
      }
     }
    }

  return longest.length;

}

这是我的工作 -

function longestVowel(str) {

  var seperateVowels = str.replace(/[bcdfghjklmnpqrstvwxyz]/ig, ' ');

  var split = seperateVowels.split(" ");

  var longest = [];
  for(var i = 0; i < split.length; i++) {
    if(longest.length === 0 && split[i] != "") {
      longest.push(split[i]);
    }  for(var j = 0; j < longest.length; j++) {
      if(split[i].length > longest[j].length) {
        longest = split[i];
      }
     }
    }

  if(typeof longest == "object") {
    return longest[0].length;
  } else {
    return longest.length;
  }

}

longestVowel("suoidea");

【问题讨论】:

  • @Vasan:你忘了说你需要跟踪你在遍历过程中看到的最高计数器值。
  • 如果你想要的只是长度,为什么不在第一个位置开始计数器并遍历字符串,如果看到非元音则重置计数器?在重置之前,如果您的当前计数器值大于当前最大值,请将计数器存储在 max 变量中。谢谢@MrSmith42
  • 非常有帮助,感谢 Vasan,这是一种更好的做事方式!

标签: javascript algorithm


【解决方案1】:

这里的线性算法O(n) 背后的想法是,您实际上只需要查看数组的每个元素一次。

在迭代的每个步骤中,我们维护两个变量globalMax 和currentMax,它们分别保存了迄今为止最长的元音子串和当前正在考虑的最长元音子串。

当遇到元音时,我们会从那里开始检查,直到遇到非元音字符为止。直到它不再是元音子串为止。这将是currentMax,我们将其与globalMax 进行比较,以检查我们是否遇到了更长的元音子字符串。所以,globalMax 是最好的 currentMax's

假设输入是'suoideaoi'

  i    |  s[i]  | currentMax  | globalMax
-------|--------|-------------|-----------
  0    |    s   |      0      |   0
  1    |    u   |      0      |   0
  2    |    o   |      1      |   1
  3    |    i   |      2      |   2
  4    |    d   |      0      |   2
  5    |    e   |      1      |   2  
  6    |    a   |      2      |   2
  7    |    o   |      3      |   3
  8    |    i   |      4      |   4 

在这里,我们计算 i = 2 to 3 的形式,因为它们是元音,但在 i = 3 我们注意到子字符串不再是元音子字符串,所以我们停在那里并将 currentMax 重置为 0。

这是一个O(n) 的原因是,一旦我们检查了元音子字符串s[2] to s[3] 即oi,我们可以确定这个元音子字符串不需要在任何可能出现的元音子字符串中进一步考虑稍后,因为在此之后有一个非元音字符,因此使任何子字符串都包含此子字符串而不是元音子字符串。

【讨论】:

    【解决方案2】:

    我喜欢您首先过滤掉非元音然后将其拆分为数组的方法。

    编辑:感谢 cmets 中的建议修改答案:

    function longestVowel(str) {
      let separateVowels = str.replace(/[^aeiou]/ig, ' ').split(' ');
      let longest;
    
      separateVowels.forEach(function(vowelGroup) {
        longest = vowelGroup.length > longest.length
          ? vowelGroup
          : longest;
      });
    
      return longest;
    }
    
    console.log(longestVowel('suoidea')); // uoi
    

    或者JavaScript 1.8/EcmaScript5:

    function longestVowel(str) {
      let separateVowels = str.replace(/[^aeiou]/ig, ' ').split(' ');
      let longest = separateVowels.reduce(function(a, b) {
        return a.length > b.length ? a : b;
      });
    
      return longest;
    }
    

    原答案: 我从那里解决这个问题的方法是按长度对数组进行排序,然后得到第一个(因此最长的)项目:

    function longestVowel(str) {
      let separateVowels = str.replace(/[bcdfghjklmnpqrstvwxyz]/ig, ' ').split(' ');
      let longest = separateVowels.sort(function (a, b) {
        return b.length - a.length;
      })[0];
    
      return longest;
    }
    
    console.log(longestVowel('suoidea')); // uoi
    

    【讨论】:

    • 我认为正则表达式可以缩短为/[^aeiou]/ig。此外,排序是O(n log n),而找到最大值可以在线性时间内完成O(n)。
    猜你喜欢
    • 2019-11-06
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 2020-12-21
    相关资源
    最近更新 更多