这几天回顾了一下DFS算法。这个算法我觉得挺重要的,思想很基础,是以后学习很多算法的基础吧,简而言之就是递归,才开始接触肯定会觉得,哇,很神奇,不知道怎么做到的,其实只需要多加练习就可以了,当初我开始刷题的时候也是懵了很久。
深度优先首先接触来自于学数据结构的图。深度优先是一种遍历搜索的方法。它的内部数据结构用栈实现,其实也可以叫做回溯算法吧。我觉得是一回事。
我第一个遇到的难题是 排列组合问题
学过高中数学的应该都有学过排列组合问题,比如1,2,3 的排列组合,是6种。
用高中的知识就是a 3 3,3的阶乘。
那么其实是可以用DFS算法的。如果可以重复的话,那么这题很简单,实话讲,我当时遇到这题确实困了挺久的。
我不懂这和递归,和DFS有什么关系。
但是我们这样想,因为每一组合它们都是一样的个数,比如上面那个例子,3。
那我们每次排列到3的时候,就返回,开始排列下一个数组,但是我们要注意不可以重复,比如这一次是1,2,3,下一次就不可以是1,2,3,包括下面所有的组合都一样。
所以这就需要记录,用visited数组来记录。
用过了就标记1,没用过就是0,只有0可以用,这样就避免了重复。
说再多也是废话,还是需要自己去练习+练习+练习。
通过大量题目累积经验。
我贴上自己的代码,展示一下自己的思路,写的并不规范。具体严谨的题目指路leetcode46.一题中等难度的题目。
#include<stdio.h>
#include<string.h>
#define LENGTH(a) (sizeof(a) / sizeof(a[0]))
int ans[10010];
int visited[10010];
int sum = 0;
void dfs(int index, int *nums, int numsSize)
{
int i, j;
if(index >= numsSize) {
sum ++;
for(j = 0; j < numsSize; j ++) {
printf("%d", ans[j]);
}
printf("\n");
return ;
}
for(i = 0; i < numsSize; i ++) {
if(visited[nums[i]] == 0) {
ans[index] = nums[i];
visited[nums[i]] = 1;
dfs(index + 1, nums, numsSize);
visited[nums[i]] = 0;
}
}
}
void permute(int n)
{
memset(visited, 0, sizeof(visited));
int a[n];
int i;
for(i = 0; i < n; i ++) {
a[i] = i + 1;
}
dfs(0, a, n);
}
int main()
{
permute(5);
printf("\n%d", sum);
return 0;
}
用ans数组来记录答案。注意在每一次递归结束后将visited置为0,方便下一次使用。
后续会持续更新DFS的问题。