zoukankan      html  css  js  c++  java
  • 5-全排列总结:

    https://www.nowcoder.com/acm/contest/76/H

    给一道题,可以去测试代码。

    这里总结一下全排列的几种方法:

    方法一:利用交换排列:缺点:不能按字典序排列,但可以借助set处理。

    #include <bits/stdc++.h>  //不会按字典序排列 
    using namespace std;
    
    void pre(string str, int s, int e){
    	if(s == e){
    		cout << str << endl;
    	}
    	else{
    		for(int i = s; i <= e; i++){
    			if(i != s && str[i] == str[s]) //去重,除了第一位,其余的相同时无须交换 
    				continue;
    			swap(str[i], str[s]);
    			pre(str, s + 1, e);
    			swap(str[i], str[s]);
    		}
    	}
    }
    
    int main(){
    	string str;
    	cin >> str;
    	pre(str, 0, str.length() - 1);
    	return 0;
    }
    

      方法二:利用dfs,只能处理没有重复元素的字符串

    #include <bits/stdc++.h>
    using namespace std;
    char str[100];
    char mu[100];
    
    void dfs(int len, int n){
    	if(len == n){
    		cout << mu << endl;
    		return ;
    	}
    	for(int i = 0; i < n; i++){ //尝试放入每个字符 
    		int flag = 1;
    		for(int j = 0; j < len; j++){ //检测这个字符是否已经放入过 
    			if(mu[j] == str[i]){
    				flag = 0;
    				break;
    			}
    		}
    		if(flag){
    			mu[len] = str[i];
    			dfs(len + 1, n); 
    		}
    	}
    }
    
    int main(){
    	cin >> str;
    	
    	sort(str, str + strlen(str)); 
    	dfs(0, strlen(str));
    	
    	return 0;
    }
    

      方法三:dfs: 感觉这个是比较理想的,可以按字典序排好输出,并能去重,一定要掌握!!!

    对于A1,B,A2进行排序,(这里的A1, A2代表相同元素,下标是为了区分)
    首先sort一下变成:A1,A2,B
    然后第一趟:
    A1,A2,B
    A1, B, A2
    然后遍历到A2开头了,好,后面查找下一个时,从i=0开始,
    于是判断A1是否访问过,未访问则进行最关键的步骤了:
    检测A1之后是否有已访问的且和A1相等,如若是则放弃A1继续遍历。
    这里有点不好理解,对于A1A2B的序列,可知A1再前所以以A开头的
    必定是以A1开头,所以在尝试A2开始头时,遍历尝试放入第二个元
    素时判断A1虽然当前未访问过,但他是在A2之前,一定在之前的全
    排列之中了,故放弃。
    感觉还是不太好理解;还是自己在纸上画画,模拟一下,多体会体会。

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e3;
    char str[N];
    char buf[N]; 
    int toal, len;
    bool visit[N];
    
    void pre(int num){
    	if(num == len){
    		cout << buf << endl;
    		toal++;
    		return ;
    	}
    	for(int i = 0; i < len; i++){
    		if(!visit[i]){
    			bool flag = 1;
    			for(int j = i + 1; j < len; j++){
    				if(visit[j] && str[j] == str[i]){ //检测重复 
    					flag = 0;
    					break;
    				}
    			}
    			if(flag){
    				buf[num] = str[i]; //这里不能写成:buf[num++] = str[i];因为for循环没有结束还要用num,不能改变num的值 
    				visit[i] = 1;
    				pre(num + 1); 
    				visit[i] = 0;
    			}
    		}
    	}
    }
    
    int main(){
    	cin >> str;
    	len = strlen(str);
    	sort(str, str + len);
    	pre(0);
    	cout << "toal: " << toal << endl;
    	return 0;
    }
    

      

  • 相关阅读:
    Kotlin入门(20)几种常见的对话框
    Kotlin入门(19)Android的基础布局
    Kotlin入门(18)利用单例对象获取时间
    Kotlin入门(17)等式判断的情况
    Kotlin入门(16)容器的遍历方式
    Kotlin入门(15)独门秘笈之特殊类
    Android Studio Gradle被墙bug总结
    unity常用的坐标系转换
    欧拉角与万向节死锁
    Unity导出Gradle工程给Android Studio使用
  • 原文地址:https://www.cnblogs.com/zhumengdexiaobai/p/8530605.html
Copyright © 2011-2022 走看看