在原地添加字符时从数组末尾循环后无法重新索引我的数组

Having trouble re-indexing my array after looping from the end of the array while adding characters in place

我正在尝试解决这个特定的算法问题:

您将获得一个表示为字符串 S 的许可证密钥,该字符串仅包含字母数字字符和破折号。字符串被 N 个破折号分成 N+1 组。

给定一个数字 K,我们希望重新格式化字符串,使每个组恰好包含 K 个字符,除了第一组可能比 K 短,但仍然必须至少包含一个字符。此外,两组之间必须插入一个破折号,并将所有小写字母转换为大写字母。

给定一个非空字符串 S 和一个数字 K,根据上述规则格式化字符串。

示例 1: 输入:S = "5F3Z-2e-9-w", K = 4

输出:“5F3Z-2E9W”

解释:字符串S被拆分成两部分,每部分4个字符。 请注意,不需要两个额外的破折号,可以将其删除。 示例 2: 输入:S = "2-5g-3-J", K = 2

输出:“2-5G-3J”

解释:字符串S已被拆分为三部分,除第一部分外每部分有2个字符,因为它可以像上面提到的那样更短。 笔记: 字符串S的长度不会超过12000,K为正整数。 字符串 S 仅包含字母数字字符 (a-z and/or A-Z and/or 0-9) 和破折号 (-)。 字符串 S 非空。

我写了下面的代码:

const licenseKeyFormatting = (S, K) => {
    //convert to array, remove special characters, and capitalize
    let s = [...S.replace(/\W/g, '').toUpperCase()]
    let pos = 1
    //from end of array add '-' for every K
    for (let i = s.length - 1; i > 0; i--) {
        if (pos === K) {
            s.splice(i, 0, '-')
            pos = 1
            i-- //re-index bc adding to the array
        }
        pos++
    }
    return s
}


console.log(licenseKeyFormatting("5F3Z-2e-9-w", 4)) //5F3Z-2E9W
console.log(licenseKeyFormatting("2-5g-3-J", 2)) //2-5G-3J
console.log(licenseKeyFormatting("a-a-a-a-", 1)) // this test case fails should be A-A-A-A, I am getting AAA-A

我很确定我的逻辑缺陷是由于重新索引造成的,但我不知道如何解决它。

我的方式....

function licenseKeyFormatting( S, K )
  {
  let arr = [...S.replace(/\W/g, '').toUpperCase()]
    , p   = 0
    ;
  for (let i=arr.length;i--;)
    {
    p = ++p % K                     // p = (p+1) % K
    if (!p&&i) arr.splice(i,0,'-')  // if p===0 and i>0
    }
  return arr.join('')
  }


console.log(licenseKeyFormatting("5F3Z-2e-9-w", 4)) // 5F3Z-2E9W
console.log(licenseKeyFormatting("2-5g-3-J", 2))   //  2-5G-3J
console.log(licenseKeyFormatting("a-a-a-a-", 1))  //   A-A-A-A  

OR: (more simple)

function licenseKeyFormatting( S, K )
  {
  let arr = [...S.replace(/\W/g, '').toUpperCase()];
  for (let p=arr.length-K;p>0;p-=K) arr.splice(p,0,'-');
  return arr.join('');
  }


console.log( licenseKeyFormatting("5F3Z-2e-9-w", 4)) // 5F3Z-2E9W
console.log( licenseKeyFormatting("2-5g-3-J", 2))   //  2-5G-3J
console.log( licenseKeyFormatting("a-a-a-a-", 1))  //   A-A-A-A

您不应更改索引。使用 splice 插入一个元素会将其他元素推回,但是因为您是从后向前迭代,所以这无关紧要。您已经处理了移位的元素。

另一个问题是在循环中设置 pos = 1。紧随其后的是 pos++。因此,当 pos 达到 K 时, pos 的值将在循环结束时重置为 2 。要么设置 pos = 0(在循环中)使其在 1 结束,要么将 pos++ 移动到 else 部分。

const licenseKeyFormatting = (S, K) => {
    //convert to array, remove special characters, and capitalize
    let s = [...S.replace(/\W/g, '').toUpperCase()]
    let pos = 1
    //from end of array add '-' for every K
    for (let i = s.length - 1; i > 0; i--) {
        if (pos === K) {
            s.splice(i, 0, '-')
            pos = 0
        }
        pos++
    }
    return s.join("") // <- added join for cleaner console output
}


console.log(licenseKeyFormatting("5F3Z-2e-9-w", 4)) //5F3Z-2E9W
console.log(licenseKeyFormatting("2-5g-3-J", 2)) //2-5G-3J
console.log(licenseKeyFormatting("a-a-a-a-", 1)) // this test case fails should be A-A-A-A, I am getting AAA-A