【如何处理重复数据】递归实现排列类型枚举 II (dfs)

递归实现排列类型枚举 II

        • 方法一:正常全排列,用set去重,会出现重复
        • 方法二:将原数组排序,重复的元素不参与继续dfs

原题链接

方法一:正常全排列,用set去重,会出现重复

#include
#include
#include

using namespace std;

int n;
int a[10];
int ans[11];
bool st[11];
set<int> s;

int get()
{
    int sum = 0;
    
    for(int i = 1; i <= n; i++)
        sum = sum*10+ans[i];
    return sum;
    
}

void dfs(int u)
{
    if(u>n)
    {
        if(s.count(get())!=0)
        {
            return;
        }
        s.insert(get());
        
        for(int i = 1; i <= n; i++)
            cout << ans[i] << ' ';
        cout << endl;
        
        return;
    }
    
    for(int i = 1; i <= n; i++)
    {
        if(st[i]==false)
        {
            ans[u]=a[i];
            st[i]=true;
            dfs(u+1);
            st[i]=false;
        }
    }
    
}

int main()
{
    cin >> n;
    
    for(int i = 1; i <= n; i++) cin >> a[i];
    
    sort(a+1,a+1+n);
    
    dfs(1);
    
    return 0;
}

方法二:将原数组排序,重复的元素不参与继续dfs

证明:
首先利用 1 2 3写出正常情况的排序
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

然后用 1 1 2
1 1 2
1 2 1
之后我们发现我们会用第二个位置的1放到 首位
1 1 2 那么这样就出现重复了

所以说,如果首位出现了1,那么首位就不能再用1
也就是接下来的代码了

while (i + 1 < n && a[i + 1] == a[i]) i ++ ;        //跳过重复,见下图
    for (int i = 0; i < n; i ++ )
        if (!st[i])
        {
            nums[u] = a[i];
            st[i] = true;
            dfs(u + 1);         //递归加1
            st[i] = false;      //还原现场

            while (i + 1 < n && a[i + 1] == a[i]) i ++ ;        //跳过重复,见下图
        }
#include 
#include 

using namespace std;

const int N = 10;

int n;
int a[N], nums[N];          //a储存排序数组, nums是输出数组
bool st[N];

void dfs(int u)
{
    if (u == n)
    {
        for (int i = 0; i < n; i ++ ) cout << nums[i] << ' ';
        cout << endl;
        return;
    }

    for (int i = 0; i < n; i ++ )
        if (!st[i])
        {
            nums[u] = a[i];
            st[i] = true;
            dfs(u + 1);         //递归加1
            st[i] = false;      //还原现场

            while (i + 1 < n && a[i + 1] == a[i]) i ++ ;        //跳过重复,见下图
        }
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++ ) cin >> a[i];

    sort(a, a + n);     //排序后重复的数字就会排在一起,便于去重

    dfs(0);

    return 0;
}

你可能感兴趣的:(dfs,&&,bfs,深度优先,算法,图论)