【问题标题】:CodeWars/ Merged String CheckerCodeWars/ 合并字符串检查器
【发布时间】:2019-03-14 13:05:45
【问题描述】:

接下来是挑战:

在工作面试中,您需要编写一个算法来检查给定的字符串 s 是否可以由另外两个字符串 part1 和 part2 组成。 限制是part1和part2中的字符与s中的字符顺序相同。 面试官给你下面的例子,告诉你从给定的测试用例中找出其余的。

我做错了什么?为什么还是失败了?

我编写了 2 个不同的脚本,但都不适用于某些测试用例

function isMerge(s, part1, part2) {
    var sArr = s.split('');
    var part1Arr = part1.split('');
    var part2Arr = part2.split('');
    var tempArr = new Array(sArr.length);
    function compareArrays(arr1, arr2){
    var count = 0;
    for (var i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) count++;
    }
    return (count == 0);
    }
    for (var i = 0; i < sArr.length; i++) {
        for (var j = 0; j < part1Arr.length; j++) {
            if (sArr[i] == part1Arr[j]) tempArr[i] = j;
        }
        for (var k = 0; k < part2Arr.length; k++) {
            if (sArr[i] == part2Arr[k]) tempArr[i] = k;
        }
    }
    alert(tempArr);
    var check = tempArr.slice();
    check.sort();
    alert(check);
    if (compareArrays(tempArr, check)) return true;
    else return false;
}
alert(isMerge('codewars', 'cdw', 'oears'));

function isMerge(s, part1, part2) {
    // create arrays of letters
    var sArr = s.split('');
    var part1Arr = part1.split('');
    var part2Arr = part2.split('');
    // create an associative array 'temp' (0:C, 1:O and so on)
    var temp = {};
    for (var k = 0; k < sArr.length; k++) {
      temp[k] = sArr[k];
    }
    // reverse an associative array 'temp' (now C:0, O:0 and so on)
    for (var key in temp) {
        var keyTemp = key;
        var keyValue = temp[key];
        key = keyValue;
        temp[key] = keyTemp;
    }
    // the function that compares arrays
    function compareArrays(arr1, arr2){
        var count = 0;
        for (var i = 0; i < arr1.length; i++) {
            if (arr1[i] !== arr2[i]) count++;
        }
        return (count == 0);
        }
    // sorting function
    function order(a, b) {
        var comparingA;
        var comparingB;
      for (var char in temp) {
          if (char == a) {
              comparingA = temp[char]; // comparingA is the number of 'a' in object 'temp'
          }
          if (char == b){
              comparingB = temp[char]; // comparingB is the number of 'b' in object 'temp'
          }
      }
        return (comparingA - comparingB);
    }
    // create copies of arrays
    var part1Sorted = part1Arr.slice();
    var part2Sorted = part2Arr.slice();
    // and sort that copies
    part1Sorted.sort(order);
    part2Sorted.sort(order);
    // If the array did not change after sorting, the order of the letters was correct
    if  (compareArrays(part1Sorted, part1Arr) && compareArrays(part2Sorted, part2Arr)) {
    // so now we can check is merge possible
    sArr = sArr.sort();
    var parts = part1Arr.concat(part2Arr);
    parts = parts.sort();
    var res = compareArrays(sArr, parts);
    return res;
    }
    return false;
}
alert(isMerge('codewars', 'code', 'wasr'));
alert(isMerge('codewars', 'oers', 'cdwa'));

我刚刚在第二个脚本中添加了 cmets

【问题讨论】:

  • 您可能需要提供“以下示例”和“给定的测试用例”,否则我们就有点摸不着头脑了。
  • 可以像数组一样迭代字符串,无需先转换。只需将函数调用的结果作为结果,如果函数返回这些值,则不需要检查并返回显式的truefalse。请使用console.log 而不是alert,它可以防止点击ok。
  • 这里是三个示例,它们在您新注释的代码中返回假阴性。这些应该返回 true:"baeabb", "b", "baeab""bdab", "bdab", ""; "bfaef", "f", "bfae";我希望这会有所帮助!

标签: javascript arrays string algorithm sorting


【解决方案1】:

我发现很难理解您的代码试图做什么。如果您提供 cmets 并解释您尝试实施的算法背后的想法,将会有所帮助。

这是一个注释的递归示例,它考虑指向第 1 部分和第 2 部分的指针 ij 是否可以构成到该点的有效合并。

function isMerge(s, part1, part2) {
  // Merge is invalid if the parts' lengths don't add up to the string's
  if (part1.length + part2.length != s.length)
    return false;
    
  // Recursive function
  function g(i, j){
    // Base case: both pointers are exactly at the end of each part
    if (i == part1.length && j == part2.length)
      return true;
    
    // One of our pointers has extended beyond the part's length,
    // that couldn't be right
    if (i > part1.length || j > part2.length)
      return false;
    
    // Just part1 matches here so increment i
    if (part1[i] == s[i + j] && part2[j] != s[i + j])
      return g(i + 1, j);
      
    // Just part2 matches here so increment j
    else if (part1[i] != s[i + j] && part2[j] == s[i + j])
      return g(i, j + 1);
      
    // Both parts match here so try incrementing either pointer
    // to see if one of those solutions is correct
    else if (part1[i] == s[i + j] && part2[j] == s[i + j])
      return g(i + 1, j) || g(i, j + 1);
      
    // Neither part matches here
    return false;
  }
    
  // Call the recursive function
  return g(0,0);
}

console.log(isMerge('codewars', 'cdw', 'oears'));
console.log(isMerge('codecoda', 'coda', 'code'));
console.log(isMerge('codewars', 'oers', 'cdwa'));
console.log(isMerge('codewars', 'cdw', 'years'));

真正长字符串的堆栈版本:

function isMerge2(s, part1, part2) {
  if (part1.length + part2.length != s.length)
    return false;
    
  let stack = [[0,0]];
  
  while (stack.length){
    [i, j] = stack.pop();
    
    if (i == part1.length && j == part2.length)
      return true;

    if (i > part1.length || j > part2.length)
      continue;
    
    if (part1[i] == s[i + j] && part2[j] != s[i + j])
      stack.push([i + 1, j]);
      
    else if (part1[i] != s[i + j] && part2[j] == s[i + j])
      stack.push([i, j + 1]);
      
    else if (part1[i] == s[i + j] && part2[j] == s[i + j]){
      stack.push([i + 1, j]);
      stack.push([i, j + 1]);
    }
  }
    
  return false;
}

function test(){
  let s = '';
  
  for (let i=0; i<1000000; i++)
    s += ['a','b','c','d','e','f','g'][~~(Math.random()*6)];
  
  let lr = {
    l: '',
    r: ''
  };
  
  for (let i=0; i<s.length; i++){
    let which = ['l', 'r'][~~(Math.random()*2)];
    
    lr[which] += s[i];
  }
  
  console.log(isMerge2(s,lr.l,lr.r));
}

test();

【讨论】:

    【解决方案2】:

    这是一种递归方法:它检查字符串的第一个字符与任一部分是否匹配,如果匹配,则递归尝试将字符串的其余部分与其余部分匹配。棘手的是,当两个部分的第一个字符相同时,您必须检查是否可以匹配其中任何一个(这解决了 Bananas 测试)。

    function isMerge(str, p1, p2) {
      if (!str.length) return !p1.length && !p2.length;
      if (p1.length && str.charAt(0) == p1.charAt(0)) {
        if (p2.length && str.charAt(0) == p2.charAt(0)) {
          return isMerge(str.substr(1), p1.substr(1), p2) || isMerge(str.substr(1), p1, p2.substr(1));
        }
        else {
          return isMerge(str.substr(1), p1.substr(1), p2);
        }
      }
      else if (p2.length && str.charAt(0) == p2.charAt(0)) {
        return isMerge(str.substr(1), p1, p2.substr(1));
      }
      else {
        return false;
      }
    }
    

    【讨论】:

    • 这段代码似乎未能通过某些测试用例。注册和尝试很容易:)
    • 哪些测试用例? @גלעדברקן
    • 这里是链接(登录并点击“火车”):codewars.com/kata/merged-string-checker
    • 感谢您的链接。我从其中一个测试名称中得到了关于我的错误在哪里的线索。这个新代码得到 76 个中的 76 个 @גלעדברקן
    【解决方案3】:

    递归调用:

    您可以使用递归方法,首先检查字符串和部分字符串的长度,然后检查长度,或者检查字符并检查给定部分字符串的其余部分。

    function isMerge(s, part1, part2) {
        if (s.length !== part1.length + part2.length) {
            return false;
        }
    
        if (!s.length) {
            return true;
        }
    
        if (part1[0] === s[0] && isMerge(s.slice(1), part1.slice(1), part2)) {
            return true;
        }
    
        if (part2[0] === s[0] && isMerge(s.slice(1), part1, part2.slice(1))) {
            return true;
        }
    
        return false;
    }
    
    console.log(isMerge('codewars', 'cdw', 'oears'));  //  true
    console.log(isMerge('codewars', 'oers', 'cdwa'));  //  true
    console.log(isMerge('codecoda', 'coda', 'code'));  //  true
    console.log(isMerge('baeabb', 'b', 'baeab'));      //  true
    console.log(isMerge('bdab', 'bdab', ''));          //  true
    console.log(isMerge('bfaef', 'f', 'bfae'));        //  true
    console.log(isMerge('codewars', 'cdw', 'years'));  // false
    console.log(isMerge('codewars', 'code', 'warss')); // false
    console.log(isMerge('codewars', 'codes', 'wars')); // false
    console.log(isMerge('', 'a', 'b'));                // false
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    使用堆栈而不是递归调用:

    function isMerge(s, part1, part2) {
        var stack = [[s, part1, part2]];
    
        if (s.length !== part1.length + part2.length) {
            return false;
        }
    
        while (stack.length) {
            [s, part1, part2] = stack.shift();
    
            if (!s.length) {
                return true;
            }
    
            if (part1[0] === s[0]) {
                stack.push([s.slice(1), part1.slice(1), part2]);
            }
    
            if (part2[0] === s[0]) {
                stack.push([s.slice(1), part1, part2.slice(1)]);
            }
        }
        return false;
    }
    
    console.log(isMerge('codewars', 'cdw', 'oears'));  //  true
    console.log(isMerge('codewars', 'oers', 'cdwa'));  //  true
    console.log(isMerge('codecoda', 'coda', 'code'));  //  true
    console.log(isMerge('baeabb', 'b', 'baeab'));      //  true
    console.log(isMerge('bdab', 'bdab', ''));          //  true
    console.log(isMerge('bfaef', 'f', 'bfae'));        //  true
    console.log(isMerge('codewars', 'cdw', 'years'));  // false
    console.log(isMerge('codewars', 'code', 'warss')); // false
    console.log(isMerge('codewars', 'codes', 'wars')); // false
    console.log(isMerge('', 'a', 'b'));                // false
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 通过:51 失败:25 错误:1
    • @Skywrath,请再试一次。
    • 时间复杂度是多少?
    • 这些似乎都失败了(它们都应该返回 false):isMerge('codewars', 'code', 'warss');isMerge('codewars', 'codes', 'wars');isMerge('', 'a', 'b');
    • Stack 很酷,但我认为您可能有错误。它会为超过 300 个长度的字符串锁定浏览器。您可以在此处查看哪些字符串似乎有问题:repl.it/@gl_dbrqn/PlayfulNastyPayware-1
    【解决方案4】:

    你可以试试下面这个吗?

    function isMerge(s, part1, part2) { 
      var result= true;
      var total = part1 + part2; 
      for (var i = 0; i < s.length; i++) { 
        var char = s.charAt(i); 
        if(total.indexOf(char) === -1) {
          result = false;
          break;
        } 
      } 
      return result;
    } 
    

    【讨论】:

    • 通过:71 失败:5 错误:1
    【解决方案5】:

    首先,您的代码可以正常工作:

    function isMerge(s, part1, part2) {
    var sArr = s.split('');
    var part1Arr = part1.split('');
    var part2Arr = part2.split('');
    var tempArr = new Array(sArr.length);
    function compareArrays(arr1, arr2){
    var count = 0;
    for (var i = 0; i < arr1.length; i++) {
        if (arr1[i] != arr2[i]) count++;
    }
    return (count == 0);
    }
    for (var i = 0; i < sArr.length; i++) {
        for (var j = 0; j < part1Arr.length; j++) {
            if (sArr[i] == part1Arr[j]) tempArr[i] = part1Arr[j];
        }
        for (var k = 0; k < part2Arr.length; k++) {
            if (sArr[i] == part2Arr[k]) tempArr[i] = part2Arr[k];
        }
    }
    alert(tempArr);
    
     if (compareArrays(tempArr, sArr)) return true;
     else return false;
    }
    alert(isMerge('codewars', 'cdw', 'oears'));
    

    现在,问题出在哪里?

    for (var j = 0; j < part1Arr.length; j++) {
    
                    /* Here you assigned the index (tempArr[i] = j;) not the char */
         if (sArr[i] == part1Arr[j]) tempArr[i] = part1Arr[j];
    }
    
    for (var k = 0; k < part2Arr.length; k++) {
    
                    /* Here you assigned the index (tempArr[i] = k;) not the char */
         if (sArr[i] == part2Arr[k]) tempArr[i] = part2Arr[k];
    }
    

    希望能帮到你;)

    【讨论】:

    • 仍然失败通过:71 失败:5 错误:1
    【解决方案6】:

    简单的合并逻辑:

    function isMerge(s, part1, part2) {
        var sArr = s.split('');
        var part1Arr = part1.split('');
        var part2Arr = part2.split('');
        
        var j = 0;
        var k = 0;
        for (var i = 0; i < sArr.length; i++) {
            if ((j < part1Arr.length) && (sArr[i] == part1Arr[j]))
              j++
            else if ((k < part2Arr.length) && (sArr[i] == part2Arr[k])) 
              k++
            else 
              break
        }
        return (j == part1Arr.length && k == part2Arr.length && (j + k) == sArr.length);
    }
    
    console.log(isMerge('abcd', 'ac', 'bd'));
    console.log(isMerge('abcd', 'acd', 'b'));
    console.log(isMerge('abcd', 'ac', 'b'));
    console.log(isMerge('abcd', 'ac', 'db'));
    console.log(isMerge('abcd', 'c', 'b'));
    console.log(isMerge('a', '', 'a'));
    console.log(isMerge('', '', ''));
    console.log(isMerge('', 'a', 'b'));
    console.log(isMerge('ab', '', ''));

    【讨论】:

    猜你喜欢
    • 2022-11-12
    • 1970-01-01
    • 2015-01-15
    • 2014-03-03
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 2015-05-29
    • 1970-01-01
    相关资源
    最近更新 更多