Skip to content
On this page

全排列

力扣题目链接:给定一个 没有重复 数字的序列,返回其所有可能的全排列。

js
输入: [1, 2, 3];
输出: [
  [1, 2, 3],
  [1, 3, 2],
  [2, 1, 3],
  [2, 3, 1],
  [3, 1, 2],
  [3, 2, 1],
];
js
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var permute = function (nums) {
  let result = [];
  let used = [];

  function backtrack(track) {
    // 结束条件
    if (track.length == nums.length) {
      // 位置1:利用es6的'... 展开运算符'进行浅拷贝
      result.push([...track]);
      return;
    }

    for (let i = 0; i < nums.length; i++) {
      if (used[i]) continue; // 跳过本次循环
      track.push(nums[i]);
      used[i] = true;
      backtrack(track);
      track.pop(); // 删除路径
      used[i] = false;
    }
  }

  backtrack([]);

  return result;
};

全排列 II

力扣题目链接:给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

js
- 输入:nums = [1,1,2]
- 输出:[[1,1,2],[1,2,1],[2,1,1]]

- 输入:nums = [1,2,3]
- 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
js
/**
 * @param {number[]} nums
 * @return {number[][]}
 *
 * ! 不同于全排列1 这里需要考虑重复的情况,所以回溯的时候加入
 * ! nums[i] == nums[i - 1] && !visited[i - 1] 进行判断(需要对数组先行排序)
 *
 */
var permuteUnique = function (nums) {
  let result = [],
    len = nums.length,
    visited = new Array(len).fill(false); // 用于剪枝

  nums.sort((a, b) => a - b); // 排序

  function backtrack(path) {
    // 判断终止条件
    if (path.length === len) {
      result.push(path.slice());
      return;
    }

    for (let i = 0; i < len; i++) {
      if (visited[i] || (nums[i] == nums[i - 1] && !visited[i - 1])) continue; // 跳过

      // 加入当前数字并置状态位为已加入选择
      path.push(nums[i]);
      visited[i] = true;
      // 继续回溯
      backtrack(path);

      // 撤销选择并还原状态位
      path.pop();
      visited[i] = false;
    }
  }

  backtrack([]);

  return result;
};

字符串的排列

剑指 Offer 38. 字符串的排列

js
输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]
js
/**
 * @param {string} s
 * @return {string[]}
 */
var permutation = function (s) {
  let result = [];
  let visited = [];

  s = s.split('').sort((a, b) => a.charCodeAt() - b.charCodeAt());

  function backtrack(track) {
    if (track.length === s.length) {
      result.push([...track].join(''));
      return;
    }

    for (let i = 0; i < s.length; i++) {
      if (visited[i] || (!visited[i - 1] && s[i] === s[i - 1])) continue;
      track.push(s[i]);
      visited[i] = true;
      backtrack(track);
      track.pop();
      visited[i] = false;
    }
  }

  backtrack([]);
  return result;
};

console.log(permutation('abb'));

字母大小写全排列

字母大小写全排列

js
输入:s = "a1b2
输出:["a1b2", "a1B2", "A1b2", "A1B2"]
js
/**
 * @param {string} s
 * @return {string[]}
 */
var letterCasePermutation = function (s) {
  let result = [];
  function dfs(i, str) {
    if (i === s.length) {
      result.push(str);
      return;
    }
    if (/\d/.test(s[i])) dfs(i + 1, str + s[i]);
    else {
      dfs(i + 1, str + s[i].toLowerCase());
      dfs(i + 1, str + s[i].toUpperCase());
    }
  }

  dfs(0, '');

  return result;
};

// 使用回溯
var letterCasePermutation = function (s) {
  let result = [];

  function backtrack(s, idx) {
    result.push(s);
    for (let i = idx; i < s.length; i++) {
      // 数字 跳过
      if (/\d/.test(s[i])) continue;
      // 字母, 反转字母大小写
      s = s.slice(0, i) + reverseStr(s[i]) + s.slice(i + 1);

      backtrack(s, i + 1);

      // 回溯, 将字母大小写反转回来
      s = s.slice(0, i) + reverseStr(s[i]) + s.slice(i + 1);
    }
  }

  function reverseStr(s) {
    return /[a-z]/.test(s) ? s.toUpperCase() : s.toLowerCase();
  }

  backtrack(s, 0);
  return result;
};

Released under the MIT License.