查找字符串b(JavaScript)中较小字符串s的所有排列

时间:2017-07-26 02:36:34

标签: javascript string algorithm

我一直试图找到针对以下问题的O(n)解决方案:找到字符串b中字符串s的字符数(排列)的数量,其中s.length将始终小于b.length

我读到最佳解决方案涉及跟踪较小字符串中字符的频率,并在滑动窗口移动较大字符串时执行相同操作,但我不确定该实现的实际方式作品。现在我的解决方案不起作用(见评论),但即使这样做,也需要O(s + sn)时间。

编辑:示例输入:('aba', 'abaab')。输出:3,因为'aba'存在于b中,从索引0开始,'baa'位于1,'aab'位于2。

function anagramsInStr(s,b) {

    //O(s)
    let freq = s.split("").reduce((map, el) => {
        map[el] = (map[el] + 1) || 1;
        return map;
    }, {});

    let i = 0, j = s.length;
    // O(n)
    for (let char in b.split("")) {
        // O(s)
        if (b.length - char + 1 > s.length) {

            let window = b.slice(i,j);

            let windowFreq = window.split("").reduce((map, el) => {
                map[el] = (map[el] + 1) || 1;
                return map;
            }, {});
            // Somewhere about here compare the frequencies of chars found in the window to the frequencies hash defined in the outer scope. 
            i++;
            j++;

        }
    }
}

1 个答案:

答案 0 :(得分:1)

阅读评论,如果您有任何疑问,请与我们联系:

function countAnagramOccurrences(s, b) {
  var matchCount = 0;

  var sCounts = {}; // counts for the letters in s
  var bCounts = {}; // counts for the letters in b

  // construct sCounts
  for (var i = 0; i < s.length; i++) {
    sCounts[s[i]] = (sCounts[s[i]] || 0) + 1;
  }

  // all letters that occur in sCounts
  var letters = Object.keys(sCounts);

  // for each letter in b
  for (var i = 0; i < b.length; i++) {
    // maintain a sliding window
    // if we already have s.length items in the counts, remove the oldest one
    if (i >= s.length) {
      bCounts[b[i-s.length]] -= 1;
    }
    // increment the count for the letter we're currently looking at
    bCounts[b[i]] = (bCounts[b[i]] || 0) + 1;

    // test for a match (b counts == s counts)
    var match = true;
    for (var j = 0; j < letters.length; j++) {
      if (sCounts[letters[j]] !== bCounts[letters[j]]) {
        match = false;
        break;
      }
    }
    if (match) {
      matchCount += 1;
    }
  }

  return matchCount;
}

console.log(countAnagramOccurrences('aba', 'abaab')); // 3

修改

关于运行时的说明:这是O(nk + m),其中 n s 的长度, m b 的长度, k b 中唯一字符的数量。由于 m 总是小于 n ,我们可以减少到O(nk),因为 k 受固定常数(大小)的限制(字母表),我们可以进一步减少到O(n)。