常见算法题剖析

全排列与爬楼梯算法

一:  

  A、题意描述: 给出一个字符串,求出其全排列。

   B、算法思想:

     如果排列后的字符串如果超过了最后一个位置, 则打印这个字符串, 返回。

    否则

    对于输入串中的每一个字符, 如果它标记为已用过, 跳过它转向下一个字符

    否则将这个字符放在当前位置, 将这个字符标记为已用过。

   从当前位置+1处开始全排列余下的字符, 将这个字符标记为未用过。

 

   C、如下我我的代码:

  /**
Administrator: lsy
2009-11-8
全排列问题
 */
public class Permutation {
 
 public static void main(String[] args) {
  Permutation p = new Permutation();
  p.permute("abc");
 }
 
     public void permute(String str){
      int length = str.length();
      boolean[] b = new boolean[length];
      StringBuilder out = new StringBuilder();
      char[] in = str.toCharArray();
      doPermute(in, out, b, length, 0);
     }

     public void doPermute(char[] in, StringBuilder out, boolean[] used, int length, int level){
      if(level == length){
       System.out.println(out.toString());
       return;
      }
      for(int i=0; i<length; i++){
       //System.out.println("used[i]: "+used[i]+"i="+i);
       if(used[i]) continue;
       out.append(in[i]);
       used[i] = true;
       doPermute(in, out, used, length, level+1);
      // System.out.println("跳出第一递归方法之后的i值为: "+ i);
       used[i] = false;
       out.setLength(out.length()-1);
      }
     }
}

 

二:  一共有50级台阶, 爬台阶的方式有一次跨一级, 一次跨两级, 一次跨三级三种方式。 请问爬完这50级台阶的方式总共有多少种?

         初看题目, 觉得与“斐波那契数列”很相似, 待代码验证  ...    ... 

————————————————————————————————————————————————————      

这个题用排列组合不好作,无法确定步骤,我提供一种方法,供大家参考借鉴:

        如果用n表示台阶的级数,a n表示某人走到第n级台阶时,所有可能不同的走法,容易弄来:

   ① 当 n=1时,显然只要1种跨法,即a 1=1。

② 当 n=2时,可以一步一级跨,也可以一步跨2级上楼,因此,共有2种不同的
跨法,即a 2=2。

③ 当 n=3时,可以一步一级跨,也可以一步三级跨,还可以第一步跨一级,第2步跨2级或第一步跨2级,第2步跨一级上楼,因此,共有4种不同的跨法,即a 3=4。

④ 当 n=4时, 分三种状况分别讨论跨法:

  如果第一步跨一级台阶,那么还剩下三级台阶,由③可知有a3 =4(种)跨法。

  如果第一步跨2级台阶,那么还剩下2级台阶,由②可知有a2 =2(种)跨法。

  如果第一步跨三级台阶,那么还剩下一级台阶,由①可知有a1 =1(种)跨法。

  根据加法原理,有a 4= a1 a2 a3 =1 2 4=7

  类推 ,有

a5= a2 a3 a4 =2 4 7=13

a6= a3 a4 a5 =4 7 13=24

a7= a4 a5 a6=7 13 24=44

a8= a5 a6 a7 =13 24 44=81

a9= a6 a7 a8 =24 44 81=149

a10= a7 a8 a9=44 81 149=274

  一般地,有

an=an-1 an-2 an-3

答:按此上楼方式,10级台阶共有274种不同走法。

   ——————————源代码如下:

   /**
Administrator: lsy
2009-11-14
爬楼梯
 */
public class ClawStep {
 
  public static void main(String[] args) {
  int times = ClawTimes(10);
  System.out.println("总共有 "+times +"种走法");
 }
 
  public static int ClawTimes(int n){
   if(n==1){
    return 1;
   }
   if(n==2){
    return 2;
   }
  
   if(n==3){
    return 4;
   }
  
   if(n>3){
    return ClawTimes(n-3)+ClawTimes(n-2)+ClawTimes(n-1);
   }
   return -1;
  }

}

 

三:   给定33个数 从33个中选6个(可以重复) 加和等于150  统计有多少种排列方法?

public static void main(String[] args) throws Exception {
       
int[] a = { 20, 15, 30, 9, 10, 23, 33, 43, 34, 21, 45, 67, 58 };
       
// thinkIn(0, 150, a, 0);
        think(0, 150, a, 0, new int[6]);
    }

   
/**
     *
     *
@param i
     *            当前考虑装载的数组下标
     *
@param totalNow
     *            当前容量
     *
@param src
     *            数据源
     *
@param size
     *            当前是第几个数了
     *
@param result
     *            结果集
    
*/
   
static void think(int i, int totalNow, int[] src, int size, int[] result) {
       
if (size == 5) {
           
if (totalNow == src[i]) {
                result[size]
= src[i];
               
for (int k = 0; k < result.length; k++) {
                    System.out.print(result[k]
+ "   ");
                }
                System.out.println();
            }
           
// 已经装了6次了
            return;
        }
       
if (totalNow < src[i]) {
           
// 不能再装了,装了就超了
            return;
        }

       
int[] r = new int[6];
        System.arraycopy(result,
0, r, 0, 6);
       
for (; i < src.length; i++) {
           
// 考虑继续装剩下的数
            r[size] = src[i];
            think(i, totalNow
- src[i], src, size + 1, r);
        }

    }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值