🌈【LeetCode 838. 推多米诺 】- JavaScript(双指针+正则)

109 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


【LeetCode 838. 推多米诺 】- JavaScript(双指针+正则)

题目描述

n 张多米诺骨牌排成一行,将每张多米诺骨牌垂直竖立。在开始时,同时把一些多米诺骨牌向左或向右推。

每过一秒,倒向左边的多米诺骨牌会推动其左侧相邻的多米诺骨牌。同样地,倒向右边的多米诺骨牌也会推动竖立在其右侧的相邻多米诺骨牌。

如果一张垂直竖立的多米诺骨牌的两侧同时有多米诺骨牌倒下时,由于受力平衡, 该骨牌仍然保持不变。

就这个问题而言,我们会认为一张正在倒下的多米诺骨牌不会对其它正在倒下或已经倒下的多米诺骨牌施加额外的力。

给你一个字符串 dominoes 表示这一行多米诺骨牌的初始状态,其中:

dominoes[i] = 'L',表示第 i 张多米诺骨牌被推向左侧, dominoes[i] = 'R',表示第 i 张多米诺骨牌被推向右侧, dominoes[i] = '.',表示没有推动第 i 张多米诺骨牌。 返回表示最终状态的字符串。

示例 1:

输入:dominoes = "RR.L" 输出:"RR.L" 解释:第一张多米诺骨牌没有给第二张施加额外的力。

正则大法

策略:

  1. 替换开头是.L的
  2. 替换结尾是R.的
  3. 替换R.L的 这个需要全局匹配
  4. 替换L.L或R.R的 需要全局匹配 但是可能存在L.L.L或R.R.R的情况 这样就会导致问题 所以需要while多次替换

几个注意点:

  1. 字符串替换,每进行一次while,相当于向左倒+向右倒一次
  2. while之前,先将已平衡的牌R.L锁定
  3. while中,若出现平衡状态的,也将其锁定
  4. 最后在解锁
function pushDominoes(str) {
  str = str
    .replace(/(^\.+L)/, (_, p1) => 'L'.repeat(p1.length))
    .replace(/(R\.+$)/, (_, p1) => 'R'.repeat(p1.length))
    .replace(/(R\.{2,}L)/g, (_, p1) => {
      const len = p1.length,
        q = Math.floor(len / 2)
      return `${'R'.repeat(q)}${len % 2 === 1 ? '.' : ''}${'L'.repeat(q)}`
    })
  const rrReg = /(L\.+L)|(R\.+R)/g
  while (rrReg.test(str)) {
    str = str.replace(rrReg, (_, p1, p2) =>
      `${p1 ? 'L' : 'R'}`.repeat(p1 ? p1.length : p2.length)
    )
  }
  return str
}

双指针

思路:当前未倒下的多米诺骨牌的状态有其左右正在倒下的多米诺骨牌的方向决定。即相近两个推到的多米诺骨牌中间的所有骨牌状态由这两个推到的骨牌状态决定。

策略:

  • 两侧骨牌倒向相同:则中间骨牌也是该方向。

  • 两侧骨牌倒向相内:则中间骨牌也向内倒。

  • 两侧骨牌倒向向外:则中间状态不改变。

需要的注意的细节是:由于已经倾倒的骨牌不会受到影响,所以只需要根据连续的直立骨牌区间整体左侧右侧骨牌的倒向状态即可判断直立骨牌的最终状态


var pushDominoes = function(dominoes) {
  if (!dominoes.length) return '';

  dominoes = dominoes.split('');

  let p = 0, q = 0;

  while(q < dominoes.length) {
    if (dominoes[q] === '.') {
      q++;
    } else if (dominoes[q] === 'L' && dominoes[p] !== 'R') {
      while(p !== q) {
        dominoes[p] = 'L';
        p++;
      }
      q++;
    } else if (dominoes[q] === 'L' && dominoes[p] === 'R') {
      let left = p, right = q;

      while(left < right) {
        dominoes[left] = 'R';
        dominoes[right] = 'L';
        left++;
        right--;
      }
      p = q;
      q++;
    } else if (dominoes[q] === 'R' && dominoes[p] === 'R') {
      while(p !== q) {
        dominoes[p] = 'R';
        p++;
      }
      q++;
    } else if (dominoes[q] === 'R') {
      p = q;
      q++;
    }
  }

  // q 溢出 但是 p指向的是R,比如这种情况,需要做特殊处理
  // 'R......'
  while(p + 1 < dominoes.length && dominoes[p] === 'R') {
    dominoes[++p] = 'R';
  }

  return dominoes.join('');
};


感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤