上一篇说了使用位运算来进行子集输出,这里使用回溯的方法来进行排序。

回溯的思想,我的理解就是:

把解的所有情况转换为树或者图,然后用深度优先的原则来对所有的情况进行遍历解析。

当然,因为问题中会包涵这各种各样的限制条件,我们可以用这些限制条件去减少遍历的分支。

其实,比较著名的就是0-1背包问题,这个背包问题之后再说,这里先看排列组合。

假设我们的数组为[6,7,8],依然使用0来表示当前数字不存在,用1来表示当前数字存在,我们就可以画出这样一个树:

这里使用递归来生成对应的flag标记,重点是backtrack函数:

#include <stdio.h>

int x[] = {6,7,8};   // 需要排列的数组
int y[] = {0,0,0}; // 存放flag标记
int level = 3; // 有3个数字需要进行排列,对应的就需要排3层 void show()
{
for (int i=0; i<level; i++)
{
printf("flag : %d ", y[i]);
}
printf("\n");
} void backtrack (int t)
{
if (t == level) // 当遍历深度等于level的时候,说明遍历完成,得到一组完整的flag标记
show();
else
for (int i=0;i<=1;i++) // 这里先生成0标记,再生成1标记
{
y[t]=i; // 记录当前层是否存在,0存在,1不存在
backtrack(t+1); // 递归遍历下一层,这里可以根据题目限制来判断是否需要继续下一层的遍历,可以减少遍历次数
}
} int main(void)
{
backtrack(0);
return 0;
} 输出结果为:
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

回溯的基本就那么一个思想,那限制条件怎么用呢?

比如,我有10元钱,这里有三个物品,价格分别是8元,5元,2元,10元,

问,这10元钱可以有哪些买法?

这里存在的一个限制就是:总数不能超过10。

#include <stdio.h>

#define TOTAL 10  // 总数最多为10

int x[] = {8,5,2,10};  // 价格
int y[] = {0,0,0,0};
int level = 4; void show()
{
int n=0;
for (int i=0; i<level; i++) // 计算总价格是否超过10
{
n += y[i] * x[i];
}
if (TOTAL < n)
{
return;
}
for (int i=0; i<level; i++) // 这里直接打印符合条件的价格
{
printf("%d ", y[i]*x[i]);
}
printf("\n");
} void backtrack (int t)
{
if (t == level)
show();
else
for (int i=0;i<=1;i++)
{
y[t]=i;
int n = 0;
for (int j=0; j<t; j++) // 这里先计算一下当前价格是多少
{
n = y[j] * x[j];
}
if (TOTAL > n) // 如果当前价格已经超了,就不需要再递归下一层(因为不论下一层是否存在,总价格必然会超),否则继续递归
backtrack(t+1);
}
} int main()
{
backtrack(0);
return 0;
}
结果为:
0 0 0 0
0 0 0 10
0 0 2 0
0 5 0 0
0 5 2 0
8 0 0 0
8 0 2 0

leadcode的Hot100系列--78. 子集--回溯的更多相关文章

  1. leadcode的Hot100系列--78. 子集--位运算

    看一个数组的子集有多少,其实就是排列组合, 比如:[0,1] 对应的子集有:[] [0] [1] [1,1] 这四种. 一般对应有两种方法:位运算 和 回溯. 这里先使用位运算来做. 位运算 一个长度 ...

  2. leadcode的Hot100系列--17. 电话号码的字母组合--回溯的另一种想法的应用

    提交leetcode的时候遇到了问题,一直说访问越界,但仔仔细细检查n多遍,就是检查不出来. 因为我用到了count全局变量,自加一来表明当前数组访问的位置, 后来突然想到,是不是在leetcode在 ...

  3. leadcode的Hot100系列--64. 最小路径和--权值最小的动态规划

    如果这个: leadcode的Hot100系列--62. 不同路径--简单的动态规划 看懂的话,那这题基本上是一样的, 不同点在于: 1.这里每条路径相当于多了一个权值 2.结论不再固定,而是要比较不 ...

  4. [LeetCode] 78. 子集 ☆☆☆(回溯)

    描述 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = [1,2,3]输出:[ [3],  [1],  [2] ...

  5. leadcode的Hot100系列--62. 不同路径--简单的动态规划

    题目比较清晰,简单来说就是: A B C D E F G H I J K L 只能往右或者往下,从A到L,能有几种走法. 这里使用动态规划的方法来做一下. 动态规划最重要的就是动态方程,这里简单说下这 ...

  6. leadcode的Hot100系列--155. 最小栈

    栈:先入后出,后入先出 像电梯一样,先进入电梯的,走到电梯最深处,后进入电梯的,站在电梯门口, 所以电梯打开的时候,后进入的会先走出来,先进入的会后走出来. push,对应入电梯,把数据往里面压 po ...

  7. leadcode的Hot100系列--206. 反转链表

    这里使用两种方式, 一个是直接从头往后遍历 -------> 迭代 一个是从最后一个往前遍历 -----> 递归 迭代 定义三个变量:pPre pNext pNow pPre表示当前节点的 ...

  8. leadcode的Hot100系列--104. 二叉树的最大深度

    依然使用递归思想. 思路: 1.树的深度 = max (左子树深度,右子树深度)+ 1 . ------> 这里的加1是表示自己节点深度为1. 2.如果当前节点为null,则说明它的左右子树深度 ...

  9. leadcode的Hot100系列--226. 翻转二叉树

    这玩意儿基本上还是遍历的那一套, 这里使用先序遍历的方式,直接对左右子树进行对调即可. (虽然看题目的时候,感觉都一样,但真正写出来之后,印象还是深刻了很多) struct TreeNode* inv ...

随机推荐

  1. 微信小程序知识集锦

    1.自定义属性/获取属性值 自定义属性: <view bindtap='shopPost' data-myid='item.goods_id' ></view> 获取属性: s ...

  2. 如何把Go调用C的性能提升10倍?

    目前,当Go需要和C/C++代码集成的时候,大家最先想到的肯定是CGO.毕竟是官方的解决方案,而且简单. 但是CGO是非常慢的.因为CGO其实一个桥接器,通过自动生成代码,CGO在保留了C/C++运行 ...

  3. 多线程——继承Thread类别

    详细java此前使用多线程,让我们来看看下面的问题. 什么是多线程     简单的理解成:cpu"同一时候"运行多个任务,这就是多线程. (究其本质,当涉及到进程和线程的概念.上面 ...

  4. boost库交叉编译(Linux生成ARM的库)

    1. 环境: Linux系统:Ubuntu 14.04 编译工具:arm-fsl-linux-gnueabi-gcc 2.下载boost源码: 地址:https://sourceforge.net/p ...

  5. SQL Server查询当前连接数

    行数就是连接数,每一行是连接详情 SELECT * FROM [Master].[dbo].[SYSPROCESSES] WHERE [DBID] IN ( SELECT [DBID] FROM [M ...

  6. XML Serialize/Deserialize

    using System; using System.Collections.Generic; using System.Globalization; using System.IO; using S ...

  7. <input type="image"> 和 <img> 用法区别

    原文:<input type="image"> 和 <img> 用法区别 w3c定义如下: Image <input type="image ...

  8. Visual Studio一直弹出“未将对象引用设置到对象的实例”对话框的处理

    试了一下,VS2017更新到最新版本的时候,会有这个错误.相当于是相当编辑XAML界面的时候会弹出,程序真正执行的时候反而不会弹出. 应该是最新的VS2017在显示XAML编辑界面的时候,会执行一部分 ...

  9. 解决C++项目使用sqlite中文乱码问题

    我参考的是这篇文章:https://www.2cto.com/database/201411/354891.html 理论是:sqlite使用的是UTF-8,C++中用的字符串是ascii或unico ...

  10. .NET解析xml字符串,通过反射给实体类对象赋值,获取实体类数据列表

    /// <summary> /// 解析xml字符串 转换为实体类列表数据 /// </summary> /// <param name="xmlStr&quo ...