算法122345

java(122345)的一道面试题  

2010-06-10 17:12:49|  分类: 数据结构--基础知 |举报 |字号 订阅

看到网上有一个不过的算法:

 

 /**
  * @param eleStr -
  *            待分配字符组成的串
  * @param rstStr -
  *            已分配字符组成的串
  */
 public void depthSearch(String eleStr, String rstStr) {
  if (eleStr.length() == 0) {
   count++;
   System.out.println(rstStr);
   return;
  }
  for (int i = 0; i < eleStr.length(); i++) {
   String currEle = eleStr.substring(i, i + 1); // 取出当前位的值
   if (rstStr.length() == 2 && "4".equals(currEle))
    continue; // 剪掉第三位为4的分支
   if (rstStr.endsWith("3") && "5".equals(currEle))
    continue; // 剪掉"35"相连的分支
   if (rstStr.endsWith("5") && "3".equals(currEle))
    continue; // 剪掉"53"相连的分支
   if(eleStr.substring(0, i).indexOf(currEle) !=  -1)
    continue; // 剪掉同一位上字符重复的分支(此题即剪掉重复的2)
  
   depthSearch(eleStr.substring(0, i) + eleStr.substring(i + 1),
     rstStr + currEle); // 用剩余的合法串继续递归
  }
 }

其中要处以的地方就是:eleStr.substring(0, i).indexOf(currEle) !=  -1

这个是去除重复的。即在一次循环中,在同一个位置上,如果这个数字已经出现过,

那就continue。比如有输入的:2365837,现在循环到后面的3的位置了,显然对于同一层的for循环是在一个位置上(第一次调用for循环,则该次循环的数字全都是在第一个位置),这样在这个for循环中已经出现过了3(意思就是这个位置上已经考虑过3了),所以在同一层循环上如果再有3,这是就要退出。






import java.util.Set;
import java.util.TreeSet;

public class MyTest {

    public static Set<String> set = new TreeSet<String>();

    public static void perm(char[] n, int beg, int end) {
        if (beg == end) {
            addNumber(String.valueOf(n));
        } else {
            for (int i = beg; i <= end; ++i) {
                swap(n, beg, i);
                perm(n, beg + 1, end);
                swap(n, beg, i);
            }
        }
    }

    public static void swap(char[] n, int x, int y) {
        if (x == y || n[x] == n[y]) {
            return;
        }
        char temp = n[x];
        n[x] = n[y];
        n[y] = temp;
    }

    public static void addNumber(String str) {
        if (str.charAt(2) == '4' || str.contains("35") || str.contains("53")) {
            return;
        }
        set.add(str);
    }

    public static void main(String args[]) {
        char[] number = new char[] { '1', '2', '2', '3', '4', '5' };
        perm(number, 0, number.length - 1);
        System.out.println(set.size());
        int cols = 10;
        for (String s : set) {
            System.out.print(s + " ");
            if (cols-- == 1) {
                System.out.println();
                cols = 10;
            }
        }
    }



package com.sw.suanfa.first.ten;

import java.util.ArrayList;
import java.util.List;

/**
 * 用java语言实现,一个组数:122345这6个数,打印出它所有可能的组合;要求4不能在第3位,3和5不能相连。
 * 我的做法:首先,我确定用递归实现。
 *          其次,不排除任何条件,打出所有的组合。
 *          在递归中增加了preNum,和level参数,可方便的对条件【4不能在第3位,3和5不能相连】进行过滤。
 *          在递归正增加了intList,便于排除重复。比如122345这个串中有2个2.则按照以上的算法会出现重复的情况。
 *          这里用了一个intList主要是利用其方法indexOf,实际也可以通过数组循环的方式来查找,这里为了方便就用了list。
 *
 * @author songwei
 * @date 2010.3.24
 *
 */
public class ComposeArray {
    
    public static void main(String[] args) {
        int len = 6;
        int[] numArray = {1,2,2,3,4,5};
        int[] currentArray = new int[len];
        getNextNumber(0,1,numArray,currentArray);
        
    }
    
    /**
     *
     * @param preNum 前一个数值
     * @param level 当前层数
     * @param numArray 当前层中能够选择的数值集合
     * @param currentArray 正在操作的数组,当这个数组中的所有值均覆值后,则为条件允许情况下的一个数值集合。
     */
    private static void getNextNumber(int preNum,int level,int[] numArray,int[] currentArray){
        List<Integer> intList = new ArrayList<Integer>();
        for(int i=0;i<numArray.length;i++){
            int currentNum = numArray[i];
            if(intList.indexOf(Integer.valueOf(currentNum))>-1) continue ;
            intList.add(currentNum);            
            
            //4不能在第3位出现
            if(level == 3 && currentNum == 4) continue ;
            if(level != 1){
                //3和5不能相连
                if((currentNum ==5 && preNum == 3) || (currentNum ==3 && preNum == 5)){
                    continue ;
                }
            }
            currentArray[level-1] = currentNum ;
            int nextLevel = level +1 ;
            if(level == currentArray.length){
                OutArray(currentArray);
                return ;
            }else{
                getNextNumber(currentNum,nextLevel,createNewArray(numArray,i),currentArray);
            }
        }
    }
    
    /**
     * 创建一个新的数组,这个数组为该次排列中,下一个level可以出现的数值集合。
     * @param oldArray
     * @param orderNumber
     * @return
     */
    private static int[] createNewArray(int[] oldArray,int orderNumber){
        if(oldArray.length<=1) return null ;
        int newLen = oldArray.length-1 ;
        int[] newArray =new int[newLen];
        int newOrderNumber = 0 ;
        for(int i=0;i<oldArray.length;i++){
            if(i == orderNumber) continue ;
            newArray[newOrderNumber] = oldArray[i];
            newOrderNumber ++ ;
        }
        return newArray;
    }
    
    private static void OutArray(int[] array){
        for(int i=0;i<array.length;i++){
            System.out.print(array[i]);
        }
        System.out.println("");
    }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值