20行 java回溯法 无优先级运算问题 含详细注释

思路回溯法:因为是操作数+操作符+操作数 这样的形式 

所以一开始要先遍历操作数后递归,然后再对操作符遍历和剩余操作数进行遍历递归。获得所有的可行的解,下面是核心函数、辅助函数和主函数,用JAVA实现。

核心函数:

public static void Math(int[] number, String[] count) {
		
		// 如果已用操作数的个数满了 则回溯
		if (getNumberNumber(number) == number.length) {
			return;
		}
		// 如果已用操作数的个数等于零 则遍历已存入操作数 进行递归 
		if (getNumberNumber(number) == 0) {
			for (int i = 0; i < figure.length; i++) {
				number[0] = figure[i];
				Math(number, count);
			}
		} else {
			// 如果存在已用操作数 则遍历操作符
			
			// 操作符遍历
			for (int i = 0; i < operator.length; i++) {
				
				// 获得之前操作数和操作符的运算结果
				int oldCal = getOldCalculateResult(number, count);
				
				// 将新的操作符存入count数组
				addCount(count, operator[i]);

				// 获得一个不在已存入操作数的操作数数组 然后在该数组里遍历操作数
				int figures[] = getAvailableFigures(number, figure);
				
				for (int j = 0; j < getNumberNumber(figures); j++) {
					
					// 获得还可以进行操作的操作数
					int nextNumber = figures[j];

					// 将操作数存入number数组
					addNumber(number, nextNumber);

					// 获得新的运算结果
					int newCal = getNewCalculateResult(oldCal, nextNumber, operator[i]);
					
					// 判断结果是否等于最终结果 若相等则打印
					if (newCal == m) {
						printResult(number, count);
					}
					// 本次操作符合操作数读取运算完毕 进行递归 
					Math(number, count);
					// 递归结束 移除刚刚存入的number操作数 等待循环遍历下一个可用的操作数
					removeNumber(number);
				}
				// 本次操作数 遍历完毕 移除刚刚存入的count操作符 等待循环下一个操作符
				removeCount(count);
			}
		}
	}
主函数:

	private static String operator[] = { "+", "-", "*", "/" }; // 存入操作符
	private static int figure[]; // 存入操作数

	private static int n, m; // 操作数个数n和结果m

	public static void main(String arg[]) {
		int number[]; // 已用操作数
		String count[] = new String[3]; // 已用操作符
		
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入N个数和结果M");
		n = scan.nextInt();
		m = scan.nextInt();
		// 初始化 
		figure = new int[n];
		number = new int[n];

		System.out.println("请输入" + n + "个数字 用空格隔开");
		for (int i = 0; i < figure.length; i++) {
			figure[i] = scan.nextInt();
		}

		System.out.println();
		Math(number, count);
	}
辅助函数:

// 获得目前存入的操作数的数量
	public static int getNumberNumber(int[] number) {
		int n = 0;
		for (int i = 0; i < number.length; i++) {
			if (number[i] != 0)
				n++;
			else
				return n;
		}
		return n;
	}

	// 获得目前存入的操作符的数量
	public static int getCountNumber(String[] count) {
		int n = 0;
		for (int i = 0; i < count.length; i++) {
			if (count[i] != null)
				n++;
			else
				return n;
		}
		return n;
	}

	// 获得两个操作数进行运算的结果
	public static int getNewCalculateResult(int oldCal, int number, String operator) {
		int result = oldCal;
		switch (operator) {
		case "+":
			result += number;
			break;
		case "-":
			result -= number;
			break;
		case "*":
			result *= number;
			break;
		case "/":
			result /= number;
			break;
		}
		return result;
	}

	// 获得number数组里的操作数 进行count数组里的操作符的 结果
	public static int getOldCalculateResult(int[] number, String[] count) {
		int result = number[0];
		for (int i = 0; i < getCountNumber(count); i++) {
			if (count[i] == null)
				return result;
			switch (count[i]) {
			case "+":
				result += number[i + 1];
				break;
			case "-":
				result -= number[i + 1];
				break;
			case "*":
				result *= number[i + 1];
				break;
			case "/":
				result /= number[i + 1];
				break;
			}
		}
		return result;
	}
	// 获得一个除了已存入操作数的数组
	public static int[] getAvailableFigures(int number[], int figure[]){
		int result[] = new int[figure.length];
		boolean[] index = new boolean[figure.length];
		for (int i = 0; i < index.length; i++) {
			index[i] = true;
		}
		for (int j = 0; j < getNumberNumber(number); j++) {
			for (int i = 0; i < figure.length; i++) {
				if (number[j] == figure[i] && index[i]) {
					index[i] = false;
					break;
				}
			}
		}
		int j = 0;
		for (int i = 0; i < figure.length; i++) {
			if(index[i]){
				result[j] = figure[i];
				j++;
			}
		}
		return result;
	}
	// 获得还可以进行参与运算的操作数 如没有 则返回-1
	public static int getAvailableFigure(int number[], int figure[]) {
		boolean[] index = new boolean[figure.length];
		for (int i = 0; i < index.length; i++) {
			index[i] = true;
		}
		for (int j = 0; j < getNumberNumber(number); j++) {
			for (int i = 0; i < figure.length; i++) {
				if (number[j] == figure[i] && index[i]) {
					index[i] = false;
					break;
				}
			}
		}
		for (int i = 0; i < index.length; i++) {
			if (index[i]) {
				return figure[i];
			}
		}
		return -1;
	}

	// 从尾部添加一个操作数
	public static void addNumber(int number[], int addNumber) {
		for (int i = 0; i < number.length; i++) {
			if (number[i] == 0) {
				number[i] = addNumber;
				return;
			}
		}
	}

	// 从尾部添加一个操作符
	public static void addCount(String count[], String addCount) {
		for (int i = 0; i < count.length; i++) {
			if (count[i] == null) {
				count[i] = addCount;
				return;
			}
		}
	}

	// 从尾部移除一个操作数
	public static void removeNumber(int number[]) {
		number[getNumberNumber(number) - 1] = 0;
	}

	// 从尾部移除一个操作符
	public static void removeCount(String count[]) {
		count[getCountNumber(count) - 1] = null;
	}

	// 打印结果
	public static void printResult(int number[], String count[]) {
		for (int i = 0; i < getNumberNumber(number); i++) {
			System.out.print(number[i]);
			if (i == getCountNumber(count)) {
				System.out.println("=" + m);
			} else {
				System.out.print(count[i]);
			}
		}
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值