求符合规则的JavaScript字符串字典序递增、递减函数实现
实现两个自定义字典序操作的JavaScript函数:递增与递减
一、递增函数(incrementString)
需求规则
接收初始字符串与增量次数n,返回n个字典序升序的字符串,需遵循:
- 特殊字符(非字母)位置与内容固定,仅在递减操作中可修改;
- 增量采用最小步长:优先修改现有字母(仅做递增),尽量不增加字符串长度;
- 使用最小必要字符串长度:仅当当前长度的字母无法继续递增时,才在末尾追加最小字母(
A)。
实现代码
function incrementString(initial, n) { const result = []; const isLetter = c => /[a-zA-Z]/.test(c); // 字母与编码映射:A-Z(0-25),a-z(26-51) const charToCode = c => { const code = c.charCodeAt(0); if (code >= 65 && code <= 90) return code - 65; if (code >= 97 && code <= 122) return code - 97 + 26; return -1; }; const codeToChar = code => { return code < 26 ? String.fromCharCode(code + 65) : String.fromCharCode(code - 26 + 97); }; // 拆分初始字符串:记录特殊字符位置与字母序列 const charLayout = []; let letterSequence = []; for (const c of initial) { if (isLetter(c)) { charLayout.push({ type: 'letter', idx: letterSequence.length }); letterSequence.push(charToCode(c)); } else { charLayout.push({ type: 'special', val: c }); } } // 从字母序列重建完整字符串 const buildStr = (letters) => { let str = ''; let letterIdx = 0; for (const item of charLayout) { str += item.type === 'special' ? item.val : codeToChar(letters[item.idx]); } return str; }; // 字母序列执行一次递增(模拟52进制进位) const incrementLetters = (arr) => { const newArr = [...arr]; let carry = 1; for (let i = newArr.length - 1; i >= 0 && carry; i--) { newArr[i] += carry; if (newArr[i] >= 52) { newArr[i] = 0; carry = 1; } else { carry = 0; } } if (carry) newArr.push(0); // 进位后追加最小字母 return newArr; }; let currentLetters = [...letterSequence]; for (let i = 0; i < n; i++) { currentLetters = incrementLetters(currentLetters); result.push(buildStr(currentLetters)); } return result; }
示例验证
- 输入:
incrementString("x", 2)→ 输出:["y", "z"] - 输入:
incrementString("x", 53)→ 输出前28项为["y", "z", "xA", "xB", ..., "xz"],后续为["yA", "yB", ...]
二、递减函数(decrementString)
需求规则
接收初始字符串与递减次数n,返回n个递减结果,需遵循:
- 字母可增删改,特殊字符仅可删除;
- 尽可能少用额外字符,结果不低于空字符串;
- 优先生成长度不小于初始长度的字符串,必要时可增加或缩短长度;
- 初始字符串非空且不全为最小字母(
A)。
实现代码
function decrementString(initial, n) { const result = []; const isLetter = c => /[a-zA-Z]/.test(c); const MIN_CODE = 0; // 对应字母A const initialLen = initial.length; // 字母与编码映射 const charToCode = c => { const code = c.charCodeAt(0); if (code >= 65 && code <= 90) return code - 65; if (code >= 97 && code <= 122) return code - 97 + 26; return -1; }; const codeToChar = code => { return code < 26 ? String.fromCharCode(code + 65) : String.fromCharCode(code - 26 + 97); }; // 生成下一个递减字符串 const getNextDecrement = (current) => { // 1. 优先生成更长的、更小的字符串(满足最小长度要求) if (current.length <= initialLen * 2) { const letters = current.split('').filter(isLetter); if (letters.length > 0) { // 扩展字母序列并将末尾字母递减,如ab → aabb const extended = [...letters, ...letters]; const lastLetterIdx = extended.findLastIndex(isLetter); const code = charToCode(extended[lastLetterIdx]); if (code > MIN_CODE) { extended[lastLetterIdx] = codeToChar(code - 1); const longerStr = extended.join(''); if (longerStr < current) return longerStr; } } } // 2. 修改现有字符生成更小的字符串 const chars = current.split(''); for (let i = chars.length - 1; i >= 0; i--) { if (!isLetter(chars[i])) continue; const code = charToCode(chars[i]); if (code > MIN_CODE) { chars[i] = codeToChar(code - 1); // 后续字母设为最大值,保证是当前前缀下的最大可能字符串 for (let j = i + 1; j < chars.length; j++) { if (isLetter(chars[j])) chars[j] = 'z'; } return chars.join(''); } } // 3. 缩短长度:先删特殊字符,再删字母 const onlyLetters = current.split('').filter(isLetter).join(''); if (onlyLetters.length < current.length) { return onlyLetters; } return current.length > 0 ? current.slice(0, -1) : ''; }; let current = initial; for (let i = 0; i < n; i++) { let next = getNextDecrement(current); // 处理特殊字符删除的特殊情况(如b$b → b$ → b) if (current.includes('$') && next === current.split('').filter(isLetter).join('')) { const temp = current.split(''); const lastSpecialIdx = temp.findLastIndex(c => !isLetter(c)); if (lastSpecialIdx !== -1) { temp.splice(lastSpecialIdx, 1); next = temp.join(''); } } // 已为空字符串时,后续均返回空 if (next === '') { result.push(next); while (++i < n) result.push(''); break; } result.push(next); current = next; } return result; }
示例验证
- 输入:
decrementString("ab", 8)→ 输出:["aabb", "aaba", "aab", "aaaa", "aaa", "aa", "a", ""] - 输入:
decrementString("b$b", 10)→ 输出:["b$a", "b$", "b", "abb", "aba", "ab", "aaa", "aa", "a", ""]
内容的提问来源于stack exchange,提问作者Matteo Glaeser
相关产品推荐
相关产品推荐

