谁能答对这道题?如有兴趣,请留下算法,呵呵~(续,递归算法)

       (续昨天)老久没来博客园了,前几天和同事一起出去玩,一个女生给我出了个题,有四个数,分别是3,3,8,8,如何才能让他们经过+, -, *, / 四则运算最后结果得到24,我想了半天没想出来,汗!!!

不过这不是俺的作风啊,于是厚着脸皮吹牛说:“哥明天写程序给你算出来!”,经过一天的努力,终于写出来个支持n位数计算结果的算法,不过自认为效率很差,想看看大家的代码,然后改一改,欢迎一起来讨论啊!

     由于本人水平有限,所以代码可读性可能很差,大家不要着急看代码,我先解释一下,我一共写了三个类,第一个类产生运算的结果队列,第二个类声明结果队列中节点的数据结构,里面有三项,第一项是Operand,操作数组成的队列,例如【8,3】&【5,3】&【8,8】;第二项是操作符号组成的队列,例如 1&0&0,其中1代表减号,0代表加号(看过程序就知道了);第三项是结果集,例如经过上面的运算 8-3+3+8,最后结果集中存的就只有16这个最后结果了 。

    好了,本程序照理说应该可以算五位数六位数的加减乘除,但是现实中只有小于等于四位的可以成功,原因是四位数加减乘除产生的结果有C42×C32×6×6×6个结果,如果出去除数为零的情况,resultlist这个队列中要有三千多个值,要是五位可能几十万个,六位就有三千多万个,晕!堆栈溢出了!那位高手可以指点一下我改进改进算法,呵呵~

ContractedBlock.gif ExpandedBlockStart.gif ResultList类
import java.math.BigDecimal;
import java.util.ArrayList;

public class ResultList {
    
public void OP(ResultNode node) {
        ArrayList Data 
= node.ResultSet;
        
if (Data.size() > 1) {
        
// 对给定的一组数中选出两个进行组合,返回组合的索引值
        ArrayList OperandIndextList = Cn2(Data,Data.size());
        
for (int i = 0; i < OperandIndextList.size(); i++) {
            
int[] OperandIndext = (int[])OperandIndextList.get(i);
            
// 由于Cn2函数返回的是索引而不是数值,所以在此转换成数值OperandData,即得到两个操作数
            BigDecimal[] OperandData = new BigDecimal[2];
            OperandData[
0= (BigDecimal)Data.get(OperandIndext[0]); 
            OperandData[
1= (BigDecimal)Data.get(OperandIndext[1]); 
            
// 返回两个操作数的结果集
            ArrayList OpResult = getResult(OperandData);
            
// 遍历结果集里的结果(共6个,如果除数为零则为五个)
            for (int j = 0; j < OpResult.size(); j++) {
                
// 在此产生一组新的数,该组数值是除掉Data中的两个操作数,加入本次的运算结果产生的,备下次递归使用
                ArrayList ResultData = (ArrayList)Data.clone();
                ResultData.remove(OperandIndext[
0]);
                ResultData.remove(OperandIndext[
1]-1);
                ResultData.add(OpResult.get(j));
                
// 生成resultList的节点实例
                ResultNode resultNode = new ResultNode();
                
// 该节点要保留递归运算中上次的操作数和操作符号,所以操组数和符号用队列存储
                resultNode.Operand = (ArrayList)node.Operand.clone();
                resultNode.Operater 
= (ArrayList)node.Operater.clone();
                
// 添加本次的两个操作数
                resultNode.Operand.add(OperandData);
                
// 添加本次运算的操作符号运算
                resultNode.Operater.add(new BigDecimal(j));
                
// 添加本次新产生的结果集
                resultNode.ResultSet = ResultData;
                resultList.add(resultNode);
            }
        }

        
// 循环递归开始
        for(int i = 0; i < resultList.size(); i++) {
            
// 所谓的newnode是上次产生的节点,作为本次的输入参数
            ResultNode newnode = (ResultNode)resultList.get(i);
            
/* 如果结果集中的结果大于一个,那么不用说,接着循环,递归,算结果吧,
             * 如果等于一个那么跳出循环,它就是最终结果。
             * 
*/
            
if (newnode.ResultSet.size() > 1) {
                resultList.remove(i);
            } 
else { break; }
            
// 递归
            OP(newnode);
        }
        }
    }
    
/*该方法产生两个操作数经过计算可能产生的所有数值,加法和乘法不必说了,
     * 注意的是减法和除法如果交换连个操作数可能产生不同的结果,所以有六种
     * 可能。
     * 
*/
    
private  ArrayList getResult(BigDecimal[] Data) {
        BigDecimal result;
        ArrayList resultList 
= new ArrayList();
        
for (int i=0; i<6; i++ ) {
            result 
= new BigDecimal(0);
            
switch(i) {
            
case 0
                result 
= Data[0].add(Data[1]);
                resultList.add(result);
                
break;
            
case 1:
                result 
= Data[0].subtract(Data[1]);
                resultList.add(result);
                
break;
            
case 2:
                result 
= Data[1].subtract(Data[0]);
                resultList.add(result);
                
break;
            
case 3:
                result 
= Data[0].multiply(Data[1]);
                resultList.add(result);
                
break;
            
case 4:
                
if (Data[1].compareTo(new BigDecimal("0")) != 0) {
                result 
= Data[0].divide(Data[1], 10, BigDecimal.ROUND_HALF_UP);
                resultList.add(result);
                }
                
break;
            
case 5:
                
if (Data[0].compareTo(new BigDecimal("0")) != 0) {
                result 
= Data[1].divide(Data[0], 10, BigDecimal.ROUND_HALF_UP);
                resultList.add(result);
                }
                
break;
            }
        }
        
return resultList;
    }
    
/*该方法从所给的所有数中选中两个作为操作数,返回值是所有可能的索引
     * 例如: 输入3 2 8,返回的组合是 12,13,23所组成的队列,
     * 而不是 32,28,38所组成的队列
     * 
*/
    
private ArrayList Cn2(ArrayList Data, int n) {
        ArrayList resultList 
= new ArrayList();
        
for (int i = 0; i < n; i++) {
            
for (int j = i + 1; j < n; j++) {
                
int[] result = new int[2];
                result[
0= i;
                result[
1= j;
                resultList.add(result);
            }
        }
        
return resultList;
    }


    
public ResultList() {
        resultList 
= new ArrayList();
    }
    
public ArrayList getResultList() {
        
return resultList;
    }
    
private ArrayList resultList;
}

 

 

ContractedBlock.gif ExpandedBlockStart.gif ResultNode 类
import java.util.ArrayList;

public class ResultNode {
    
public ArrayList Operand;
    
public ArrayList Operater;
    
public ArrayList ResultSet;
    
public ResultNode() {
        Operand 
= new ArrayList();
        Operater 
= new ArrayList();
        ResultSet 
= new ArrayList();
    }
}

 

 

ContractedBlock.gif ExpandedBlockStart.gif 测试类
import java.math.BigDecimal;

public class TestResutList {
    
public static void main(String[] args) {
        
// 输入要计算的数值
        ResultNode beginNode = new ResultNode();
        beginNode.ResultSet.add(
new BigDecimal("3"));
        beginNode.ResultSet.add(
new BigDecimal("3"));
        beginNode.ResultSet.add(
new BigDecimal("8"));
        beginNode.ResultSet.add(
new BigDecimal("8"));
        
// 计算的目标值
        BigDecimal goal = new BigDecimal("24");
        
// 计算得出结果队列
        ResultList resultlist = new ResultList();
        resultlist.OP(beginNode);
        
        
// 遍历结果队列,如果找出满足条件的一个节点,则打印节点信息,然后跳出循环
        for (int i =0 ; i< resultlist.getResultList().size(); i++) {
            
// 节点
            ResultNode node = (ResultNode)resultlist.getResultList().get(i);
            
// 节点存储的结果
            BigDecimal result = (BigDecimal)node.ResultSet.get(0);
            
// 转换精度
            BigDecimal rscl = result.setScale(5,BigDecimal.ROUND_HALF_UP);
            
// 如果满足条件,打印结果
            if ( rscl.compareTo(goal)==0) {
                
for (int j = 0; j < node.Operand.size(); j ++) {
                    BigDecimal[] Operand 
= (BigDecimal[])node.Operand.get(j);
                    
switch(((BigDecimal)node.Operater.get(j)).intValue()) {
                        
case 0:
                            System.out.print(
"Operand: "+Operand[0]);
                            System.out.print(
" ");
                            System.out.print(Operand[
1]);
                            System.out.print(
"  ");
                            System.out.println(
"Operater: "+"+");
                            
break;
                        
case 1:
                            System.out.print(
"Operand: "+Operand[0]);
                            System.out.print(
" ");
                            System.out.print(Operand[
1]);
                            System.out.print(
"  ");
                            System.out.println(
"Operater: "+"-");
                            
break;
                        
case 2:
                            System.out.print(
"Operand: "+Operand[1]);
                            System.out.print(
" ");
                            System.out.print(Operand[
0]);
                            System.out.print(
"  ");
                            System.out.println(
"Operater: "+"-");
                            
break;
                        
case 3:
                            System.out.print(
"Operand: "+Operand[0]);
                            System.out.print(
" ");
                            System.out.print(Operand[
1]);
                            System.out.print(
"  ");
                            System.out.println(
"Operater: "+"*");
                            
break;
                        
case 4:
                            System.out.print(
"Operand: "+Operand[0]);
                            System.out.print(
" ");
                            System.out.print(Operand[
1]);
                            System.out.print(
"  ");
                            System.out.println(
"Operater: "+"/");
                            
break;
                        
case 5:
                            System.out.print(
"Operand: "+Operand[1]);
                            System.out.print(
" ");
                            System.out.print(Operand[
0]);
                            System.out.print(
"  ");
                            System.out.println(
"Operater: "+"/");
                            
break;
                            
                    }
                }
                
break;
            }
        }
        
    }
}

转载于:https://www.cnblogs.com/yucongqingshi/archive/2009/04/30/1447239.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值