请用数字填空,使正面十句话都正确,用java找出答案

问题:请用数字填空,使正面十句话都正确

0在这十句话里出现的次数是______
1在这十句话里出现的次数是______
2在这十句话里出现的次数是______
3在这十句话里出现的次数是______
4在这十句话里出现的次数是______
5在这十句话里出现的次数是______
6在这十句话里出现的次数是______
7在这十句话里出现的次数是______
8在这十句话里出现的次数是______
9在这十句话里出现的次数是______

题目分析:
这十句话里统计的都是数字,将每句话前面已知的数字可以提取出字符串"0123456789";
同理,后面次数的10个数字也提取出一个未知的字符串"??????????";
然后将两个字符串0-9的出现的次数统计出来跟后面次数比较得出答案;

解题步骤:
由于第一个字符串得知0-9每个数字最少出现了1次;
所有数字出现次数总和是20次(已经知数字10个+未知数字10个),最多不超过21次(其中某个数字可能超过9次);
单个数字不超过11次(假如数字都只出现1次,那么1就出现了11次);
所以后面次数的10个数字加起来>=20 && <=21,单个数字<=11;
最后得出未知的字符串为10个[1-11]的数字,这10个数字相加=20||=21。

	
	/**
	 * 找出这10个数字
	 * @param totalCount 剩下的总次数
	 * @param arr 10个数字的数组j
	 * @param i	从第几个数字开始找
	 * @return
	 * 查找方式:从第一个数字开始的最大次数开始找,找剩下数字的所有组合,如果找不到就-1;
	 * 剩下数字的次数总数不超过21减去前面数字的总次数;
	 * 同时注意每一位数字最大11;
	 * 
	 * 11,10,0,0,0,0,0,0,0,0 第一轮第一个数字最大11,剩余次数(21-11=10)顺到下一位;
	 * 11,9,1,0,0,0,0,0,0,0 第二轮第二个数字减1,剩余次数(21-11-9=1)顺到下一位(第三位);
	 * 11,9,1,0,0,0,0,0,0,0 第二轮第二个数字减1,剩余次数(21-11-9=1)顺到下一位(第三位);
	 * 11,9,0,1,0,0,0,0,0,0 第三轮第三个数字减1,剩余次数(21-11-9-0=1)顺到下一位(第四位),每个数字直到减到0,上一位才减1;
	 * ... 
	 * 10,11,0,0,0,0,0,0,0,0 直接第二个数字减到0,第一位才减1,然后剩余次数(21-10=11)顺到下一位
	 * 10,10,1,0,0,0,0,0,0,0
	 * ...
	 * 0,0,0,0,0,0,0,0,0,0 直到全部减到0则判断无解
	 */
	public static boolean findCount(int totalCount, int[] arr, int i){
		int count = totalCount > 11 ? 11 : totalCount;	//每个数字最大不超过11次
		if(i < arr.length){
			do{
				arr[i] = count;
				int remainCount = totalCount - arr[i];
				if(remainCount == 0){ //如果没有剩余次数了就判断是否匹配
//					System.out.println(join(arr));
					if(checkNum(arr)){
						return true;
					}
				}else{
					//如果当前数字组合不结果不匹配则找该剩下组合
					if(findCount(remainCount, arr, i + 1)){
						return true;
					}
				}
				//当前数字找不到就找下一个数字
				count--;
			}while(count >= 0 && i < arr.length - 1);
			//如果全部组合不匹配则归零,上一位数字减1重新匹配
			arr[i] = 0;
		}
		return false;
	}
	
	/**
	 * 测试数组的结果对不对
	 * @param arr
	 * @return
	 */
	public static boolean checkNum(int[] arr){
		String s = "0123456789" + join(arr).replace(",", ""); //将所有数字合并成一个字符串,统计出现次数
		boolean isTrue = true;
		String ss = s.toString();
		for (int i = 0; i < arr.length; i++) {
			//统计每个数字出现次数并判断是否符合结果
			int count = ss.length() - ss.replaceAll(""+i, "").length();
			if(arr[i] != count){
				isTrue = false;
				break;
			}
		}
		return isTrue;
	}
	
	public static void main(String[] args) {
		int[] arr = new int[10];
		//假如总次数为21次,从第1位开始查找
		if(findCount(21, arr, 0)){
			System.out.println("结果是:");
			for (int i = 0; i < arr.length; i++) {
				System.out.println(i + "出现次数:" + arr[i]);
			}
		}else{
			System.out.println("无解");
		}
		arr = new int[10];
		//假如总次数为20次,从第1位开始查找
		if(findCount(20, arr, 0)){
			System.out.println("结果是:");
			for (int i = 0; i < arr.length; i++) {
				System.out.println(i + "出现次数:" + arr[i]);
			}
		}else{
			System.out.println("无解");
		}

		arr = new int[10];
		//假如0出现次数为1次,总次数为20次,从第2位开始查找
		arr[0] = 1;
		if(findCount(19, arr, 1)){
			System.out.println("结果是:");
			for (int i = 0; i < arr.length; i++) {
				System.out.println(i + "出现次数:" + arr[i]);
			}
		}else{
			System.out.println("无解");
		}
	}
	

    public static String join(final int[] array) {
        if (array == null) {
            return null;
        }
        char separator = ',';
        int startIndex = 0;
        int endIndex = array.length;
        final StringBuilder buf = new StringBuilder(endIndex * 16);
        for (int i = startIndex; i < endIndex; i++) {
            if (i > startIndex) {
                buf.append(separator);
            }
            buf.append(array[i]);
        }
        return buf.toString();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值