一看就懂,一写就懵?搞懂回溯算法,一口气刷了20多道题(中)

简介: 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。——摘自《百度百科》

解题代码


var totalNQueens = function (n) {
    let count = 0; //皇后可放置的总数
    let isValid = (row, col, board, n) => {
        //所在行不用判断,每次都会下移一行
        //判断同一列的数据是否包含
        for (let i = 0; i < row; i++) {
            if (board[i][col] === 'Q') {
                return false
            }
        }
        //判断45度对角线是否包含
        for (let i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
            if (board[i][j] === 'Q') {
                return false
            }
        }
        //判断135度对角线是否包含
        for (let i = row - 1, j = col - 1; i >= 0 && j >= 0; j--, i--) {
            if (board[i][j] === 'Q') {
                return false
            }
        }
        return true
    }
    let backTracing = (row, board) => {
        //走到最后一行,统计次数
        if (row === n) {
            count++;
            return
        }
        for (let x = 0; x < n; x++) {
            //判断该位置是否可以放置 皇后
            if (isValid(row, x, board, n)) {
                board[row][x] = 'Q'; //放置皇后
                backTracing(row + 1, board); //递归
                board[row][x] = '.'; //回溯,撤销处理结果
            }
        }
    }
    backTracing(0, board)
    let board = [...Array(n)].map(v => v = ([...Array(n)]).fill('.')) //棋盘
    return count
};


2.4 - 78. 子集


给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。


解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。


示例 1:

输入:nums = [1,2,3]

输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]


示例 2:

输入:nums = [0]

输出:[[],[0]]


提示:

1 <= nums.length <= 10

-10 <= nums[i] <= 10

nums 中的所有元素 互不相同


解题思路


  1. 枚举出所有可选的数;加入选项;
  2. 撤销加入的选项,将选项加入结果


解题代码


const subsets = (nums) => {
    const res = [];
    const backTracing = (index, list) => {
        res.push(list.slice());     // 调用子递归前,加入解集
        for (let i = index; i < nums.length; i++) { // 枚举出所有可选的数
            list.push(nums[i]);       // 选这个数
            backTracing(i + 1, list);         // 基于选这个数,继续递归
            list.pop();               // 撤销选这个数
        }
    };
    backTracing(0, []);
    return res;
};


2.5 - 77. 组合



给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。


你可以按 任何顺序 返回答案。


示例 1:

输入:n = 4, k = 2

输出:

[

 [2,4],

 [3,4],

 [2,3],

 [1,2],

 [1,3],

 [1,4],

]


示例 2:

输入:n = 1, k = 1

输出:[[1]]

提示:

1 <= n <= 20

1 <= k <= n


解题思路


  1. 枚举出所有可选的数;加入选项;
  2. 撤销加入的选项,将选项加入结果
  3. 剪枝条件:选项的长度满足条件;


9.JPG


解题代码


/**
 * @param {number} n
 * @param {number} k
 * @return {number[][]}
 */
var combine = function (n, k) {
    let result = [];
    let backTracing = (start, path) => {
        // 如果已经选满了的话,加入结果集中
        if (path.length == k) {
            result.push(path.slice());
            return;
        }
        // 从开始的数字到末尾的数字
        for (let i = start; i <= n; i++) {
            // 加入选择列表中
            path.push(i);
            // 继续深度搜索
            backTracing(i + 1, path);
            // 撤销选择
            path.pop(i);
        }
    };
    backTracing(1, []);
    return result;
};


2.6 - 081. 允许重复选择元素的组合



给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。


candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。


对于给定的输入,保证和为 target 的唯一组合数少于 150 个。


示例 1:

输入: candidates = [2,3,6,7], target = 7

输出: [[7],[2,2,3]]


示例 2:

输入: candidates = [2,3,5], target = 8

输出: [[2,2,2,2],[2,3,3],[3,5]]


示例 3:

输入: candidates = [2], target = 1

输出: []


示例 4:

输入: candidates = [1], target = 1

输出: [[1]]


示例 5:

输入: candidates = [1], target = 2

输出: [[1,1]]


提示:

1 <= candidates.length <= 30

1 <= candidates[i] <= 200

candidate 中的每个元素都是独一无二的。

1 <= target <= 500


解题思路


  1. 将当前元素加入到选项里面,并将计算结果,传到选项,继续递归;
  2. 当选项和大于目标值时,结束这个选项,直到找到符合的选项,并将选项加入结果;

10.JPG


解题代码


var combinationSum = function (candidates, target) {
    const result = [], visited = [];
    backTracing(0, 0);
    return result;
    function backTracing(sum, cur) {
        if (target === sum) result.push(visited.slice());
        if (target <= sum) return;
        for (let i = cur; i < candidates.length; i++) {
            visited.push(candidates[i]); //加入到选项里面
            backTracing(sum + candidates[i], i);//选择这个选项,继续递归
            visited.pop(); //插销这个选择
        }
    }
};


2.7 - 216. 组合总和 III


找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。


说明:

所有数字都是正整数。

解集不能包含重复的组合。


示例 1:

输入: k = 3, n = 7

输出: [[1,2,4]]


示例 2:

输入: k = 3, n = 9

输出: [[1,2,6], [1,3,5], [2,3,4]]


解题思路


同组合1


解题代码


var combinationSum3 = function (k, n) {
    let ans = [];
    let backTracing = (start, path) => {
        if (path.length === k && path.reduce((acc, prev) => acc += prev) === n) {
            ans.push(path.slice())
            return
        }
        for (let i = start; i <= 9; i++) {
            path.push(i)
            backTracing(i + 1, path)
            path.pop(i)
        }
    }
    backTracing(1, [])
    return ans
};


2.8 - 17. 电话号码的字母组合



给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。


给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。


11.JPG

示例 1:

输入:digits = "23"

输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]


示例 2:

输入:digits = ""

输出:[]


示例 3:

输入:digits = "2"

输出:["a","b","c"]


提示:

0 <= digits.length <= 4

digits[i] 是范围 ['2', '9'] 的一个数字。


解题思路


  1. 找到当前按钮对应的字母字符串
  2. 拼接按钮对应的字符串组合
  3. 选项满足长度,加入结果

12.JPG


解题代码


var letterCombinations = function (digits) {
    if(!digits.length) return []
    const dic = {
        2: 'abc',
        3: 'def',
        4: 'ghi',
        5: 'jkl',
        6: 'mno',
        7: 'pqrs',
        8: 'tuv',
        9: 'wxyz',
    }, ans = [];
    let backTracing = (cur, index) => {
        if (index > digits.length - 1) { //选项满足长度,加入结果
            ans.push(cur)
            return
        }
        let curDic = dic[digits[index]] //找到当前按钮对应的字母字符串
        for (let prop of curDic) {
            backTracing(cur + prop,index+1) //拼接按钮对应的字符串组合
        }
    }
    backTracing('', 0)
    return ans
};


2.9 - 08.01. 三步问题



三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。


示例1:

输入:n = 3

输出:4

说明: 有四种走法


示例2:

输入:n = 5

输出:13

提示:

n范围在[1, 1000000]之间


解题代码(会超时)


var waysToStep = function (n) {
    let ans = [], map = [1, 2, 3]
    let backTracing = (path, sum) => {
        if (sum >= n) {
            if (sum == n) {
                ans++;
            }
            return
        }
        for (let i = 0; i < 3; i++) {
            path.push(map[i]);
            backTracing(path, sum + map[i])
            path.pop(i)
        }
    }
    backTracing([], 0)
    return ans
};


动态规划解法



/**
 * @param {number} n
 * @return {number}
 */
var waysToStep = function (n) {
    let dp =[],mod = 1000000007;
    dp[0]=0,dp[1]=1,dp[2]=2,dp[3]=4;
    for (let i = 4; i <= n; i++) {
        dp[i] = (dp[i - 1] + dp[i - 2] + dp[i - 3]) % mod
    }
    return dp[n]
};
相关文章
|
1月前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
数据结构与算法系列学习之串的定义和基本操作、串的储存结构、基本操作的实现、朴素模式匹配算法、KMP算法等代码举例及图解说明;【含常见的报错问题及其对应的解决方法】你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
|
1月前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习(8)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
1月前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
1月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
1月前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构的基本概念;算法的基本概念、特性以及时间复杂度、空间复杂度等举例说明;【含常见的报错问题及其对应的解决方法】
|
1月前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之王道第2.3章节之线性表精题汇总二(5)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
IKU达人之数据结构与算法系列学习×单双链表精题详解、数据结构、C++、排序算法、java 、动态规划 你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
|
算法
”回溯算法“框架及练习题
”回溯算法“框架及练习题
43 0