likes
comments
collection
share

数字与运算符的深搜排列

作者站长头像
站长
· 阅读数 35

最近新出的活动 数字谜题 一点也不简单,怎么算的呢这是😭

于是我想让计算机来帮我计算,把可能性都算一遍,把数字和+-x/的排列出来,然后先计算*/,再计算+- 但是我忽略了一个事就是有的时候也需要先计算+-

像今天关于 1 2 3 4 5+ - x x 得到24的结果可以是4*5+(3-1)*2, 但是由于我没有使用到(),我只能遍历得到 4*5+3-1*2 以至于一直得不到24 呜呜,所以接下来的代码只针对不用()就可以得到结果的题目😜(括号想想就好麻烦呀)

什么是深搜(dfs)呢,也就是把所有能走的路都走一遍, 因此当数据量过多的时候,就会非常耗时....

首先创建全局的变量

数字与运算符的深搜排列

// 全部数字
static String []num = { "77", "1", "6", "1", "3", "13", "11"};
// 全部符号
static String [] operator = {"-", "-", "/", "+"};
// 最终结果
static String ansNum = "66";
// 数字个数和符合个数(主要用于我们在深搜中判断它们是不是都用上了)
static int numCount = num.length, operatorCount = operator.length;
// 一个标记,保证每个数字/字符只用一次
static boolean [] bn, bo;
public static void main(String[] args) {
    bn = new boolean[numCount];
    bo = new boolean[operatorCount];
    for( int i = 0 ; i < numCount; i++ )
        bn[i] = false;
    for( int i = 0 ; i < operatorCount; i++ )
        bo[i] = false;
    // fun(排列的字符串, 当前使用的数字个数,当前使用的字符个数, 该位置能否使用运算符)
    // 第一个位置不能是运算符
    fun( "", 0, 0, false );
}

排列函数, 排列好后去计算该排列字符串,如果是我们要的结果,就打印输出

private static void fun( String s, int kn, int ko, boolean flag) {
    // 当数字和符合全部用完 且最后一个位置不是符号,则去计算
    if( kn == numCount && ko == operatorCount && flag == true) {
        String ans = calculate(s);
        // 判断是不是 66 ,
	if( ans.equals(ansNum)) {
            System.out.println(s);
	}
	return;
    }
    //	当前位置可以是数字
    for( int i = 0 ; i < numCount ; i++ ) {
        if(bn[i] == false) {
            // 回溯, 深搜必备
            bn[i] = true;
            fun( s+num[i], kn+1, ko, true );
            bn[i] = false;
	}
    }
    //当前位置可以是符号(和上面代码差不多)
    if( flag == true ) {
	for( int j = 0 ; j < operatorCount ; j++ ) {
            if(bo[j] == false) {
		bo[j] = true;
		fun( s+operator[j], kn, ko+1, false );
		bo[j] = false;
	    }
	}
    }
}

依次计算 x / + - , 假如是1-3x4-5 发现x(乘号),找出它前面和后面的数(3、4),并计算出来,替换掉1-12-5

        private static String calculate(String str) {
		String s = str;
		for( int i = 0 ; i < s.length() ; i++ ) {
                // x 号的下标
			int cindex = s.indexOf("x");
			if( cindex != -1 ) {
                            // find(x 号的下标, 当前字符串(随时会改变),符号)
                            s = find( cindex, s , "x");
                            // System.out.println(s);
			}
		}
		for( int i = 0 ; i < s.length() ; i++ ) {
			int cindex = s.indexOf("/");
			if( cindex != -1 ) {
				s = find( cindex, s , "/");
			}
		}
		for( int i = 0 ; i < s.length() ; i++ ) {
			int cindex = s.indexOf("+");
			if( cindex != -1 ) {
				s = find( cindex, s , "+");
			}
		}
		for( int i = 0 ; i < s.length() ; i++ ) {
			int cindex = s.indexOf("-");
			if( cindex != -1 ) {
				s = find( cindex, s , "-");
			}
		}
           // 将运算完的字符串返回回去
		return s;
        }

find 函数 ,找出符合前面和后面的数,并进行替换

private static String find(int cindex, String s, String op) {
		String a = "", b = "";
		for( int j = cindex-1; j >= 0; j-- ) {
			int ch = s.charAt(j)-'0';
			if( ch >= 0 && ch <= 9 ) {
				a = s.charAt(j) + a;
			}else {
				break;
			}
		}
		for( int j = cindex+1; j < s.length(); j++ ) {
			int ch = s.charAt(j)-'0';
			if( ch >= 0 && ch <= 9 ) {
				b = b + s.charAt(j);
			}else {
				break;
			}
		}
                // 将 "3x4" 替换为 "12"
		if( op == "x" ) {
			s = s.replace(a+"x"+b, Integer.toString(Integer.parseInt(a)*Integer.parseInt(b)));
		}
		if( op == "/" ) {
                // 除得尽我们才替换
			if( Integer.parseInt(a)%Integer.parseInt(b) == 0 )
				s = s.replace(a+"/"+b, Integer.toString(Integer.parseInt(a)/Integer.parseInt(b)));
		}
		if( op == "+" ) {
			s = s.replace(a+"+"+b, Integer.toString(Integer.parseInt(a)+Integer.parseInt(b)));
		}
           // 当字符串为 `-3+5+6` 负号前面没有数
		if( op == "-"  &&  a!="" ) {
			s = s.replace(a+"-"+b, Integer.toString(Integer.parseInt(a)-Integer.parseInt(b)));
		}
           // 可能会计算出来负数
		s = s.replace("+-", "-");
           s = s.replace("--", "+");
		return s;
	}

输出: 数字与运算符的深搜排列 有重复应该是因为有重复数字组合的问题

数字与运算符的深搜排列

这关过啦,虽然不能解决所有的关卡🧐🧐🧐

转载自:https://juejin.cn/post/7068572923971239973
评论
请登录