在javascript中使用子字符串/切片进行递归

时间:2016-11-09 04:44:42

标签: javascript string algorithm

编写递归算法以获取字符串的字谜。 字符串abc的预期输出为['abc', 'acb', 'bac', 'bca', 'cab', 'cba']

但是,我得到的是[ 'abc', 'acb', 'ba', 'cab', 'cba' ]

我知道问题出在哪里: 当递归返回到0级(意味着str ==='abc'和i == 1)时,子串工作(exracts'a'),但切片不工作(不提取c)。

function anagramPermutationMemo(str, memo, resultsArr, level) {
    if (!memo) {
        memo = '';
        resultsArr = [];
        level = 0;
    }
    console.log('str -', str);
    console.log('memo -', memo, '\n');

    if (str.length === 0) {
        resultsArr.push(memo);
        return;
    }
    for (var i in str) {
        console.log('level', level);
        console.log('str', str);
        console.log('i -', i, str[i]);
        console.log('substring', str.substring(0, i));
        console.log('slice', str.slice(i + 1));
        var newStr = str.substring(0, i).concat(str.slice(i + 1));
        console.log('newStr - ', newStr, '\n');
        anagramPermutationMemo(newStr, memo + str[i], resultsArr, level + 1);
    }
    level -= 1;
    console.log('backtrack', level,'\n');

    return resultsArr;
};

2 个答案:

答案 0 :(得分:1)

如果您还记录i+1(您传递给slice)的值,这将有所帮助。 problem with your for…in enumeration是枚举属性,即字符串。您的i将为"0""1""2"(如果使用可枚举方法扩展String.prototype,则可能还有其他内容)。

当你为它添加1时,它会进行字符串连接,你最终会得到"01""11""21"而不是所需的数字。鉴于slice将其参数转换为数字,"01"实际上按照需要工作,但其他的将在字符串结束后导致索引,因此您最终完全省略这些部分:

anagramPermutationMemo("abc".substring(0, "1")+"abc".slice("11"), ""+"abc"["1"], […], 0+1);
//                                                         ^^^^ should be 2
anagramPermutationMemo("a",                                       "b",           […], 1);
//                      ^ should be "ac"

要解决此问题,只需使用标准for (var i=0; i<str.length; i++)循环。

答案 1 :(得分:0)

  

我知道问题出在哪里

问题是for..in循环。

说明:

variable循环的{p> for..inString,而不是Number。括号内的符号

str[i]

返回预期结果,因为object的属性是一个字符串,例如str["0"]; Number也可用于在括号表示法str[0]中获取对象的属性。

String.prototype.slice()调用ToInteger参数,但不使用sign

将字符串转换为数字而不返回预期结果
  

ToInteger

     

抽象操作ToInteger将其参数转换为整数   数值。这个抽象操作的功能如下:

     
      
  1. 设number是输入参数上调用ToNumber的结果。
  2.   
  3. 如果number为NaN,则返回+0。
  4.   
  5. 如果number为+ 0,-0,+∞或-∞,则返回数字。
  6.   
  7. 返回计算结果sign(数字)×floor(绝对(数字))。
  8.   

String.prototype.substring()期望Number作为参数。

  

如果任一参数为NaN或为负,则将其替换为零;如果   两个参数都大于String的长度,它是   替换为String的长度。

解决方案,用for循环代替for..in循环

function anagramPermutationMemo(str, memo, resultsArr, level) {
  if (!memo) {
    memo = '';
    resultsArr = [];
    level = 0;
  }
  console.log('str -', str);
  console.log('memo -', memo, '\n');

  if (str.length === 0) {
    resultsArr.push(memo);
    return;
  }
  for (var i = 0; i < str.length; i++) {
    console.log('level', level);
    console.log('str', str);
    console.log('i -', i, str[i]);
    console.log('substring', str.substring(0, i));
    console.log('slice', str.slice(i + 1));
    var newStr = str.substring(0, i).concat(str.slice(i + 1));
    console.log('newStr - ', newStr, '\n');
    anagramPermutationMemo(newStr, memo + str[i], resultsArr, level + 1);
  }
  level -= 1;
  console.log('backtrack', level, '\n');

  return resultsArr;
};

var p = anagramPermutationMemo("abc");

console.log(p);

解决方案:

i使用Number运算符在+调用.substring().slice()时使用for..in投放Number参数} loop,其中方法的参数期望function anagramPermutationMemo(str, memo, resultsArr, level) { if (!memo) { memo = ''; resultsArr = []; level = 0; } if (str.length === 0) { resultsArr.push(memo); return; } for (var i in str) { var newStr = str.substring(0, +i).concat(str.slice(+i + 1)); var _newStr = str.substring(0, i).concat(str.slice(i + 1)); console.log(`newStr with string as parameter:${_newStr}`); console.log(`newStr with number as parameter:${newStr}`); console.log(`i:${str.substring(0, i)}, ${str.slice(i + 1)}`); console.log(`+i:${str.substring(0, +i)}, ${str.slice(+i + 1)}`) anagramPermutationMemo(newStr, memo + str[i], resultsArr, level + 1); } level -= 1; return resultsArr; }; Object.defineProperty(String, "abc", { value:123, enumerable:true }) var p = anagramPermutationMemo("abc"); console.log(p);

class User(db.Model):
    name = db.StringProperty(required=True)
    pw_hash = db.StringProperty(required=True)
    email = db.StringProperty()

    @classmethod
    def by_id(cls, uid):
        return cls.get_by_id(uid, parent=users_key())

    @classmethod
    def by_name(cls, name):
        u = cls.all().filter('name=', name).get()
        return u

    @classmethod
    def register(cls, name, pw, email=None):
        pw_hash = make_pw_hash(name, pw)
        return cls(parent=users_key(),
                    name=name,
                    pw_hash=pw_hash,
                    email=email)

    @classmethod
    def login(cls, name, pw):
        u = cls.by_name(name)
        if u and valid_pw(name, pw, u.pw_hash):
            return u