2017JavaA组-2九数算式

题目:
在这里插入图片描述

分三步完成:第一步是全排列数字,第二步是将乘号放入不同的位置,第三步是判断得到的乘积是否是不同的数字。

第一步使用最熟悉的套路,没有重复元素的全排列数组来完成,和2014年的六角填数重复,该代码后为六角填数代码。然后在套路的输出那里执行第二步。

第二步我想的是依次对数字做10的倍数的乘积,每次有8种乘积方式,想实现方法的时候想的比较杂乱。而老师的做法也是这个思路,不过非常清晰:先分别调用两个数组转整数的函数,乘号的位置用传的参数不同(起始位置和结束位置不同)来表示。然后再将两个整数相乘。后面再自己实现数组转整数的函数。

第三步我想的是依次对数字做10的倍数的除法,这样做的时间复杂度比较高。老师的做法是,将得到的乘积结果(整数)转成字符串,先判断得到的结果是不是9个数(剪枝),然后依次将字符存入hashset利用hashset是一个不允许有重复元素的集合的性质,通过最后的hashset长度是否为9来判断是否有重复数字(这里要排除数字中有0的情况)

联想:

  • 字符串转整数:Integer.parseInt(array[i])
  • 整数转字符串: Sring s = x + “”
  • 数组转字符串:Arrays.toString(newArray)

小知识点:

  • int x; String s = x+"";//就可以把整数变成字符串
  • 使用HashSet来判断字符串内是否有重复:
    • HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
    • HashSet 允许有 null 值。
    • HashSet 是无序的,即不会记录插入的顺序。
  • int indexOf(String str) :返回第一次出现的指定子字符串在此字符串中的索引,如果此字符串中没有这样的字符,则返回 -1。

坑:

  • 最后的数字里面不能有0

  • 最后答案除以二

  • 关于Java中形参与实参的理解:https://blog.csdn.net/czh500/article/details/88636612:

    1)形参为基本类型时,对形参的处理不会影响实参。

    2)形参为引用类型时,对形参的处理会影响实参。

    3)String,Integer,Double等immutable类型的特殊处理,可以理解为值传递,形参操作不会影响实参对象。

代码:

import java.util.HashSet;
import java.util.Set;

public class NineNumbers {
	static int ans;

	static void permutation(int[] a, int p)// 参数是否需要数组(如果数组是static全局变量就不需要)
	{
		if (p == 9) {
			for (int i = 1; i <= 8; i++) {
				int i1 = atoi(a, 0, i);// 不取结尾(i),这样跟下面就没有重复数字
				int i2 = atoi(a, i, 9);
				if (check(i1 * i2))
					ans++;
			}
		}
		for (int i = p; i < 9; i++) {
			swap(a, p, i);// p可以取8,跟a[i]交换
//			int t = a[i]; a[i] = a[p]; a[p] = t;
			permutation(a, p + 1); // 但p+1为9时一次全排完成,进入if
			swap(a, p, i);
//			t = a[i]; a[i] = a[p]; a[p] = t;
		}
	}

	
	  static void swap(int[] a, int i, int j) { int temp = a[i]; a[i] = a[j]; a[j] = temp; }
	 

	static int atoi(int[] a, int i, int j) {
		int sum = 0;
		int p = 1;
		for (int k = j - 1; k >= i; k--) {
			sum += p * a[k];
			p = p * 10;
		}
		return sum;
	}

	static boolean check(int i) {
		String s = i + "";
		if (s.length() != 9 || s.indexOf("0") > -1) {
			return false;
		}

		Set<Character> set = new HashSet<Character>();
		for (int j = 0; j < s.length(); j++) {
			set.add(s.charAt(j));
		}

		return set.size() == 9;
	}

	public static void main(String[] args) {
		int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
		permutation(a, 0);
		System.out.println(ans / 2);
	}
}

六角填数的全排列代码,老师的做法是把if里面的加法都先写出来赋给不同变量,用变量代替加法从而代码更加清晰:

public class SixAngle {

	static int[] a = {2, 4, 5, 6, 7, 9, 10, 11, 12};
	
	static void permutation(int k) {
		if(k == a.length) {
			if(3+8+a[0]+a[1] == 1+a[0]+a[2]+a[3] && 1+a[0]+a[2]+a[3] == 8+a[2]+a[4]+a[5]) {
				if(8+a[2]+a[4]+a[5] == 3+a[7]+a[6]+a[5] && 3+a[7]+a[6]+a[5] == a[8]+a[6]+a[4]+1) {
					if(a[8]+a[6]+a[4]+1 == a[8]+a[7]+a[1]+a[3]) {
						System.out.println(a[0]);
						return;
					}
				}
			}
		}
		for(int i = k; i < a.length; i++) {
			int t = a[k]; a[k] = a[i]; a[i] = t; //a[k]和其后的所有a[i]交换都会交换一次
			permutation(k + 1);//子数组进行全排列
			t = a[k]; a[k] = a[i]; a[i] = t;//为了下一次交换,这次交换回来
		}
	}
	
	public static void main(String[] args) {
		permutation(0);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值