算法 全排列问题,组合问题,子集问题

算法 全排列问题,组合问题,子集问题

子集问题

public class Solution {
    public List<List<Integer>> subsets(int[] S) {
        Arrays.sort(S);
        List<List<Integer>> res=new ArrayList<List<Integer>>();
        if(S==null||S.length<=0)return res;
        List<Integer> list=new ArrayList<Integer>();
     
        rec1(S,0,S.length-1,list,res);
        
        return res;
    }
    void rec(int[] S,int s,int e,List<Integer> list,List<List<Integer>> res){
        if(s==e+1){
            List<Integer> temp=new ArrayList<Integer>();
            temp.addAll(list);
            res.add(temp);
            return;
        }else{
                int i=s;
                list.add(S[i]);
                int index=list.size()-1;
                rec(S,i+1,e,list,res);
                list.remove(index);
                rec(S,i+1,e,list,res);
           
        }
        
    }
    void rec1(int[] S,int s,int e,List<Integer> list,List<List<Integer>> res){
        if(true){
            List<Integer> temp=new ArrayList<Integer>();
            temp.addAll(list);
            res.add(temp);
          
        }
        for(int i=s;i<=e;i++){
             list.add(S[i]); int index=list.size()-1;
               rec1(S,i+1,e,list,res);
                 list.remove(index);
               
        }
    }
   
}


1.子集的选择即是对元素的二选一,加入集合,不加入集合

2.注意结束条件是e+1

3.递归参数是i+1而不是s+1


组合问题:

public class Solution {
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> res=new ArrayList<List<Integer>>();
        
        if(n<=0||k<=0)return res;
       
        List<Integer> list=new ArrayList<Integer>();
        perm(k,1,n,list,res);
      
        return res;
        
    }
   void perm(int k, int s, int e, List<Integer> list,
			List<List<Integer>> res) {
		if (list.size() == k) {
			List<Integer> newlist = new ArrayList<Integer>();
			newlist.addAll(list);
			res.add(newlist);
			return;
		} else {
			for (int i = s; i <= e; i++) {
				list.add(i);
				int t = list.size();
				perm(k, i + 1, e, list, res);
				list.remove(t - 1);
			}
		}
	}
    
}

1.注意组合中的参数是i+1,其他地方与排列类似

perm(k, i + 1, e, list, res);
2.这里结束条件应该也是e+1

八皇后

  1. bool isOk(int *t)  
  2. {  
  3.     int i, j;  
  4.     for (i = 1; i <= 8; i ++) {  
  5.         for (j = i + 1; j <= 8; j ++) {  
  6.             if (i - j == t[i] - t[j] || i - j == t[j] - t[i])  
  7.                 return false;  
  8.         }  
  9.     }  
  10.     return true;  
  11. }  
  12.    
  13. void getperm(int *t,int s,int e)  
  14. {  
  15.      if(s>=e){  
  16.      if(isOk(t))  
  17.              {  
  18.                         num++;  
  19.                         a[num][0]=0;  
  20.                         for(int i=1;i<=8;i++){  
  21.                                  a[num][0]=a[num][0]*10+t[i];  
  22.                                 a[num][i]=t[i];  
  23.                         }  
  24.                         v.push_back(a[num][0]);  
  25.              }  
  26.              return;  
  27.      }else{  
  28.          for(int i=s;i<=e;i++)  
  29.          {  
  30.                  swap(t,s,i);              
  31.                  getperm(t,s+1,e);  
  32.                  swap(t,s,i);  
  33.          }  
  34.      }  
  35. }  

字符串全排列输出

void getperm(char* str,int s,int e)
{
     if(s==e)
     {
             cout<<str<<endl;return;
     }else
     {
          for(int i=s;i<=e;i++)
          {
                  swap(str,s,i);
                  getperm(str,s+1,e);
                  swap(str,s,i);
          }          
     }
}

基本模板就是这样

1.找到递归的出口,s==e,len==size-1之类,全排列不是e+1是因为,前面的排列决定好后,末位也固定了

2.递归循环实现全排列,先将s与操作值i交换,然后递归,再交换回来

3.注意这里的递归参数是s+1,区别于组合中的参数i+1

 getperm(str,s+1,e);


特别的全排列:

剑指OFFER中的 题12:打印1到最大的n位数

//  这里的全排列是因为每一位都要从0到9显示一次

void func(int n)
{
	char * number=new char[n+1];
	number[n]='\0';
	int index=0;
	for(int i=0;i<10;i++)
	{
		number[index]='0'+i;
		getrec(number,index,n);
	}
	delete [] number;
}
void getrec(char * number,int index,int n)
{
	if(index==n-1)
	{
		output(number);// 从第一个不为0的字符开始显示
	}else
	{
		for(int i=0;i<10;i++)
		{
			number[index+1]='0'+i;
			getrec(number,index+1,n);			
		}	
	}
}
void output(char *str)
{
<span style="white-space:pre">	</span>if(str==NULL)return;
<span style="white-space:pre">	</span>while(*str=='0');
<span style="white-space:pre">	</span>cout<<*str<<endl;<span style="white-space:pre">	</span>
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值