数字拆分问题算法回溯_回溯算法
知乎上有类似的文章,不过是用python讲解,我改成JS了,并加了不少题目。
78 .子集
题目描述:给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
思路:
回溯方法,一般有固定模板,此题模板为要记住.
回溯一般都是递归方法.
var subsets = function(nums) {
if(!Object(nums).length){
return []
}
var result = [];
nums.sort()
backtrack(result, [], nums, 0, nums.length);
return result;
};
function backtrack(result, tempList, nums, start, n){
result.push(tempList.concat());//没有长度限制,就直接放 result 中 for(var i = start; i< n; i++){
tempList.push(nums[i]) //试探 backtrack(result, tempList, nums, i + 1, n) ; //对结果集的子序列保证顺序,那么i+1 //即 tempList可以是[1,2],不能是[2, 1] tempList.pop() //不管成功与否,退回上一步 }
}
90.子集II
题目描述:给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: [1,2,2]
输出:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
思路:
这道题与上道题区别在于,数组里包含了重复数组,一般有两种办法.
var subsetsWithDup = function (nums) {
if (!Object(nums).length) {
return [];
}
var result = [];
nums.sort();
backtrack(result, [], nums, 0, nums.length);
return result;
};
function backtrack(result, tempList, nums, start, n) {
result.push(tempList.concat());//没有长度限制 for (var i = start; i < n; i++) {
if (i > start && nums[i] == nums[i - 1]) {//★在过程中防止重复 continue
}
tempList.push(nums[i]) //试探 backtrack(result, tempList, nums, i + 1, n); //对结果集的子序列保证顺序,那么i+1 tempList.pop(); //不管成功与否,退回上一步 }
}
subsetsWithDup([4, 4, 4, 1, 4])
//============== var subsetsWithDup2 = function (nums) {
if (!Object(nums).length) {
return [];
}
nums.sort();
var result = [], candidate = [], hash = {};
backtrack2(result, candidate, nums, 0, nums.length, hash);
return result;
};
function backtrack2(result, candidate, nums, start, n, hash) {
if(!hash[candidate]){ //在结果中进行防止重复 result.push(candidate.concat());//没有长度限制 hash[candidate] = 1;
}
for (var i = start; i < n; i++) {
candidate.push(nums[i]) //试探 backtrack2(result, candidate, nums, i + 1, n, hash);
candidate.pop(); //不管成功与否,退回上一步 }
}
subsetsWithDup2([4, 4, 4, 1, 4])
46.全排列
题目描述:给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
思路:
全排列意思就是找出它所有组合, 有两种办法 :
var permute = function (nums) {
var result = [];
if (!Object(nums).length) {
return result;
}
backtrack(result, [], nums, 0, nums.length, {});
return result;
};
function backtrack(result, candidate, nums, start, n, hash) {
if (candidate.length === n) { //对子序列有长度限制 result.push(candidate.concat());
} else {
for (var i = 0; i < n; i++) {
//注意排列解,i需要从零开始,确保它怎么也会加入某一个解, //hash是保证每一个解产生不同的关键 if (!hash[i]) {
var el = nums[i];
hash[i] = 1;
candidate.push(el); //试探 backtrack(result, candidate, nums, start + 1, n, hash);
candidate.pop(); //不管成功与否,退回上一步 hash[i] = 0;
}
}
}
}方法2,见下面图示
var permute = function (nums) {
if (!Object(nums).length) {
return [];
}
var result = [];
backtrack(result, nums, 0, nums.length);
return result;
};
function backtrack(result, nums, start, n) {
if (nums.length === start) {//到达最后一位 result.push(nums.concat());
}else{
for (var i = start; i < n; i++) {
swap(nums, i, start);
backtrack(result, nums, start + 1, n);
swap(nums, i, start);
}
}
}
function swap(nums, i, j) {
var temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
47.全排列II
题目描述:给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
思路: 与子集II很相似。
var permuteUnique = function (nums) {
if (!Object(nums).length) {
return [];
}
var result = [];
result.hash = {};//用于结果集过滤 nums.sort();
backtrack(result, [], nums, 0, nums.length, {});//这个hash用于不重复添加元素 return result;
};
function backtrack(result, tempList, nums, start, n, hash) {
if (tempList.length === n) {
var key = tempList +""
if(!result.hash[key]){
result.push(tempList.concat());
result.hash[key] = 1
}
} else {
for (var i = start; i < n; i++) {//对结果集的子序列不保证顺序, 通过hash保证不重复添加,i总是从0开始 var el = nums[i]
if (hash[i]) {
continue;
}
// if (i > 0 && nums[i] == nums[i - 1] && !hash[i-1] ) { 在地程中防止重复,比较难理解,不建议用 // continue; // } hash[i] = 1 //ce tempList.push(el) //试探 backtrack(result, tempList, nums, i, n, hash); //递归自身,i不会变化 tempList.pop(); //不管成功与否,退回上一步 hash[i] = 0;
}
}
}
17. 电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
2,3总共对应6个字母,但它是保证abc是排第一,再排def,因此不是纯的全排列。可以参考46题。
var table = {
2: ['a', 'b', 'c'],
3: ['d', 'e', 'f'],
4: ['g', 'h', 'i'],
5: ['j', 'k', 'l'],
6: ['m', 'n', 'o'],
7: ['p', 'q', 'r', 's'],
8: ['t', 'u', 'v'],
9: ['w', 'x', 'y', 'z'],
}
function letterCombinations(nums) {
if (!Object(nums).length) {
return []
}
var result = []
backtrack(result, [], nums, 0, nums.length);
return result;
}
function backtrack(list, tempList, nums, start, n) {
if (tempList.length == n) {
list.push(tempList.join(''));
} else {
for (var i = start; i < n; i++) {
var rows = table[nums[i]];
for (var j = 0; j < rows.length; j++) {
tempList.push(rows[j]);
backtrack(list, tempList, nums, i + 1, n);//i+1, 保证结果集的子序列有序 tempList.pop();
}
}
}
}
console.log(letterCombinations('23'))
console.log(letterCombinations('22'))
另一种更简洁的方法
var dict = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"];
function letterCombinations(digits) {
var result = []
if (!Object(digits).length) {
return result;
}
backtrack(result, [], digits, 0);
return result;
}
function backtrack(result, tempList, digits, start) {
if (start == digits.length) {
result.push(tempList.join(''));
} else {
var str = dict[digits[start]];
for (var i = 0; i < str.length; i++) {
tempList.push(str[i]);
backtrack(result, tempList, digits, start + 1);//start+1, 保证结果集的子序列有序 tempList.pop();
}
}
}
39. 组合总和
题目描述:给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例:
输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
代码:
function combinationSum(nums, target) {
if (!Object(nums).length) {
return [];
}
nums.sort()
var result = [], candidate = []
//最后一个参数会每次被减去一个元素,直到为零 backtrack(result, candidate, nums, 0, nums.length, target);
return result;
};
function backtrack(result, candidate, nums, start, n, target) {
if (target === 0) {
result.push(candidate.concat());
} else if (target > 0) {
for (var i = start; i < n; i++) {
candidate.push(nums[i]) //试探 //注意这里i没有加1,因为我们可以重复使用该位置的元素 backtrack(result, candidate, nums, i, n, target - nums[i]);
candidate.pop(); //不管成功与否,退回上一步 }
} //因为可以无限使用,target会不断被减,因此必须加上target大于零的条件}
combinationSum([2, 3, 6, 7], 7)
40. 组合总和II
题目描述:给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
示例:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
思路:
每个数字只能用一次
代码:
var combinationSum2 = function (nums, target) {
if (!Object(nums).length) {
return [];
}
nums.sort()
var result = [];
result.hash = {};
backtrack(result, [], nums, 0, nums.length, target);
return result;
};
function backtrack(result, tempList, nums, start, n, target) {
if (target === 0) {
var key = tempList +""
if(!result.hash[key]){ //在结果集中去重 result.push(tempList.concat());
result.hash[key] = 1;
}
} else if (target > 0) {
for (var i = start; i < n; i++) {//i不断向后,就保证只用一次 tempList.push(nums[i]) //试探 backtrack(result, tempList, nums, i+1, n, target - nums[i]); //i+1, 保证结果集的子序列有序 tempList.pop(); //不管成功与否,退回上一步 }
}
}
216. 组合总和 III
题目描述:
找出k个数字的所有可能组合,它们加起来等于一个数字n,假设只能使用1到9之间的数字,并且每个组合应该是一组唯一的数字。
确保集合中的数字按升序排序。
示例:
Input: k = 3, n = 7
Output:
[[1,2,4]]
Input: k = 3, n = 9
Output:
[[1,2,6], [1,3,5], [2,3,4]]
思路:
其实就是对数组[1,2,3,4,5,6,7,8,9]取子集,其和为n,并保证其长度为k
var combinationSum3 = function (k, target) {
var result = []
if (!k) {
return result;
}
backtrack(result, [], k, 1, target);
return result;
};
function backtrack(result, tempList, k, start, target) {
if (tempList.length > k) {
return
}
if (target === 0) {
if (tempList.length === k) {
result.push(tempList.concat());
}
} else if (target > 0) {
for (var i = start; i < 10; i++) {//注意每次的起点不一样 tempList.push(i) //试探 backtrack(result, tempList, k, i + 1, target - i); //递归自身, i递增,保证只用一次 tempList.pop(); //不管成功与否,退回上一步 }
}
}
131.分割回文串
题目描述:给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
示例:
输入: "aab"
输出:
[
["aa","b"],
["a","a","b"]
]
思路:
回溯算法
代码:
var partition = function (str) {
if (!Object(str).length) {
return [];
}
var result = [];
backtrack(result, [], str, 0, str.length);
return result;
};
function backtrack(result, tempList, str, start, n) {
if (start === n) {
result.push(tempList.concat());
} else {
for (var i = start; i < n; i++) {//注意从0开始,不断尝试 if (isPalindrome(str, start, i)) {
var el = str.substring(start, i + 1)
tempList.push(el) //试探 backtrack(result, tempList, str, i + 1, n); //递归自身 tempList.pop(); //不管成功与否,退回上一步 }
}
}
}
function isPalindrome(s, low, high) {
while (low < high)
if (s.charAt(low++) != s.charAt(high--)) return false;
return true;
}
console.log(partition('aab'))
数字拆分问题算法回溯_回溯算法相关推荐
- 迪杰斯特拉算法c++_《算法图解》学习记录7--迪杰斯特拉算法
本章内容 继续图的讨论,介绍加权图--提高或降低某些边的权重. 介绍狄克斯特拉dijstra算法,让你能够找出加权图中前往X的最短路径. 介绍图中的环,它导致狄克斯特拉算法不管用. 在前一 ...
- python贪心算法最短路径_贪心算法---最短路径问题
一,贪心算法的设计思想 • 从问题的某一个初始解出发逐步逼近给定的目标,每一步都作一个不可回溯的决策,尽可能地求得最好的解.当达到某算法中的某一步不需要再继续前进时,算法停止. 二,贪心算法的基本性质 ...
- 排序中减治法算法伪代码_【算法与数据结构】伪代码与流程图
js难的是抽象概念 编程语言也能抽象 JS Python java PHP 根本就没区别 这些语言都有 声名 if...else while 循环 for 循环 函数 对象 这意味着 你没有必要过分关 ...
- 多类感知器算法题目_先进算法讲解
一想到你在关注我就忍不住有点紧张 ●先进算法● 数学建模中一些常用的算法,比如神经网络算法.遗传算法.模拟退火算法和模糊数学方法等可以较容易地解决一些很复杂.常规算法很难解决的问题.这些算法都有很深的 ...
- python迭代算法含义_迭代算法原理及其Python编程实现
黄旭 摘 要:迭代算法是数学算法在计算机中应用的一个热点,也是计算机解决问题的一般思路,本文结合数学中二分法求根的原理,阐述了数学迭代算法的一般原理,并采用了Python加以实现,为进一步对数学算法理 ...
- k中心点聚类算法伪代码_聚类算法之——K-Means、Canopy、Mini Batch K-Means
K-Means||算法 K-Means||算法是为了解决K-Means++算法缺点而产生的一种算法: 主要思路是改变每次遍历时候的取样规则,并非按照K-Means++算法每次遍历只获取一个样本,而是每 ...
- k均值聚类算法优缺点_聚类算法之——K-Means算法
聚类算法属于无监督学习,它将相似的对象归到同一个簇中.K-Means算法是聚类算法中最常用到算法: 1. 预备知识点 距离计算 闵可夫斯基距离 点 之间的闵可夫斯基距离为 欧式距离 点 之间的欧氏距离 ...
- 正确率能很好的评估分类算法吗_机器学习算法优缺点对比及选择(汇总篇)
转自:机器学习与统计学 本文的目的,是务实.简洁地盘点一番当前机器学习算法.文中内容结合了个人在查阅资料过程中收集到的前人总结,同时添加了部分自身总结,在这里,依据实际使用中的经验,将对此模型优缺点及 ...
- 数字拆分问题算法回溯_回溯算法:求子集问题!
给「代码随想录」一个星标吧! ❝ 认识本质之后,这就是一道模板题 通知:我将公众号文章和学习相关的资料整理到了Github :https://github.com/youngyangyang04/le ...
最新文章
- 谨慎对待switch,用Object对象替换switch
- IOS学习笔记二十一(NSDictionary、NSMutableDictionary)
- 徒手实现Spring的IOC
- 三位数除以两位数竖式计算没有余数_苏教四上期末复习——两、三位数除以两位数...
- java if两个条件_java(3) if结构
- 为什么感觉赚100万很难?
- 计算机上已安装某个第三方应用程序,防止电脑第三方软件“被”安装 3招彻底屏蔽不明软件...
- ant 改变表格数据_查找相同数据还在一次一次使用vlookup函数?只需加上它1次搞定...
- Cypress Locators
- 畅玩新方式 | Google Play 游戏 Beta 版在 PC 上发布
- windows手动清理垃圾文件
- 解决VMware虚拟机由于不小心更改文件路径导致的桌面图标变白,运行exe程序显示找不到路径的错误
- CSS 语法 网贷黑户正规查询系统,通过CSS选择器控制怎么查自己带过的网贷数量做一个个人网贷记录查询软件
- electron start之后index.html页面不显示
- 热插拔与非热插拔的区别
- WIN8系统的远程桌面漏洞 利用QQ拼音纯净版实现提权
- 【R】【决策树】【随机森林】
- Android小项目集合100多个
- python无需下载就可使用的标准模块
- #BDA#笔记#加餐:EXCEL实操