论坛首页 Java企业应用论坛

吸血鬼数字 高效算法

浏览 8689 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (3)
作者 正文
   发表时间:2010-03-11   最后修改:2010-03-11
提前声明. 此算法来自 【老紫竹】.
老紫竹CSDN ID:java2000_net
主页http://www.laozizhu.com
废话不多说.直接上代码
package com.javaeye.arrick.util;
import java.util.Arrays;   
/**  
 * 吸血鬼数字,高效率版本.<br>  
 * 一个4位数字,可以拆分2个2位数数字的乘积,顺序不限。<br>  
 * 比如 1395 =15 * 93  
 *   
 * @author 老紫竹(laozizhu.com)  
 */  
public class VampireNumber {   
  public static void main(String[] arg) {   
    String[] ar_str1, ar_str2;   
    int sum = 0;   
    int from;   
    int to;   
    int i_val;   
    int count = 0;   
    // 双重循环穷举   
    for (int i = 10; i < 100; i++) {   
      // j=i+1避免重复   
      from = Math.max(1000 / i, i + 1); //返回两个int值中较大的一个
      to = Math.min(10000 / i, 100);   //返回两个int值中较小的一个
      for (int j = from; j < to; j++) {   
        i_val = i * j;   
        if (i_val % 100 == 0 ||(i_val - i - j) % 9 != 0) {   
          continue;   
        }   
        count++;
        ar_str1 = String.valueOf(i_val).split("");   
        ar_str2 = (String.valueOf(i) + String.valueOf(j)).split("");   
        Arrays.sort(ar_str1);   
        Arrays.sort(ar_str2);
        if (Arrays.equals(ar_str1, ar_str2)) {
           // 排序后比较,为真则找到一组
           // 返回两个Objects数组彼此相等,返回true
          sum++;   
          System.out.println("第" + sum + "组: " + i + "*" + j + "=" + i_val);   
        }   
      }   
    }   
    System.out.println("共找到" + sum + "组吸血鬼数");   
    System.out.println(count);   
  }   
}  

运行结果
第1组: 15*93=1395
第2组: 21*60=1260
第3组: 21*87=1827
第4组: 27*81=2187
第5组: 30*51=1530
第6组: 35*41=1435
第7组: 80*86=6880
共找到7组吸血鬼数
232

count 次数只有232.. 已经算是最高效的了.
而主要的高效代码 只有3行代码
if (i_val % 100 == 0 ||(i_val - i - j) % 9 != 0) {   
  continue;   
}   

而已
i_val % 100 -->都明白什么意思.
(i_val - i -j) % 9 !=0 --> 也许一时想不明白.
请看如下逻辑. 你会一目了然
算法解释:
假设
i_val = 1000a + 100b + 10c + d,
因为满足i_val = x * y,
则有x = 10a + b, y = 10c + d
则i_val - x - y = 990a + 99b + 9c = 9 * (110a + 11b + c)
所以i_val - x - y能被9整除。
所以满足该条件的数字必定能被9整除,所以可以直接过滤其他数字。
完毕.
《Thinking in Java》 (Dan Forhan推荐练习代码)
   发表时间:2010-03-12   最后修改:2010-03-12
吸血鬼数字更高效版本 …… 屠夫版:
http://butcher.iteye.com/blog/613750

呃,我的是检验而非穷举 ……
0 请登录后投票
   发表时间:2010-03-12  
最好能说一下解题的思路
0 请登录后投票
   发表时间:2010-03-12  
东四环屠夫 写道
吸血鬼数字更高效版本 …… 屠夫版:
http://butcher.iteye.com/blog/613750

呃,我的是检验而非穷举 ……

Ruby. 不会. 嘿嘿.
0 请登录后投票
   发表时间:2010-03-12  
vieri122 写道
最好能说一下解题的思路

  回头补上吧.
0 请登录后投票
   发表时间:2010-03-12  
东四环屠夫 写道
吸血鬼数字更高效版本 …… 屠夫版:
http://butcher.iteye.com/blog/613750

呃,我的是检验而非穷举 ……


写的不错 ,但是仔细看了一下 检验的算法也这差不多的思路 应该不会更高效率 只是ruby api的强大 看起来更简洁
0 请登录后投票
   发表时间:2010-03-12  
to = Math.min(10000 / i, 100);   //返回两个int值中较小的一个 
for (int j = from; j < to; j++) {  
  ......
}

直接写 for (int j=from; j<100; j++) 就可以了。因为i的取值是从10到100,所以10000/i肯定是大于等于100的。
0 请登录后投票
   发表时间:2010-03-12   最后修改:2010-03-13
东四环屠夫 写道
吸血鬼数字更高效版本 …… 屠夫版:
http://butcher.iteye.com/blog/613750

呃,我的是检验而非穷举 ……


感觉两个二位数字穷举,比检验四位数更高效

AsWater 写道
to = Math.min(10000 / i, 100);   //返回两个int值中较小的一个 
for (int j = from; j < to; j++) {  
  ......
}

直接写 for (int j=from; j<100; j++) 就可以了。因为i的取值是从10到100,所以10000/i肯定是大于等于100的。


恩,to不需要
0 请登录后投票
   发表时间:2010-03-13   最后修改:2010-03-13
用string数组不可能高效,改成int数组,时间消耗大概只有原来的1/9


package com.kwzh;

import java.util.Arrays;

public class VampireNumber {

	public static void main(String[] args) {
		float f = System.nanoTime();
		new VampireNumber().vampireArray();
		System.out.println("string array: " + (System.nanoTime() - f)
				+ " nano seconds");
		f = System.nanoTime();
		new VampireNumber().vampireArray2();
		System.out.println("int array: " + (System.nanoTime() - f)
				+ " nano seconds");
	}

	public void vampireArray() {
		int small, big, product, floor = 10, ceil = 100;
		int from, count = 0, sum = 0;
		String[] ar_str1, ar_str2;
		for (small = floor; small < ceil; small++) {
			from = Math.max(1000 / small, small + 1);
			for (big = from; big < ceil; big++) {
				product = small * big;
				if (product % 100 == 0 || (product - small - big) % 9 != 0) {
					continue;
				}
				ar_str1 = String.valueOf(product).split("");
				ar_str2 = (String.valueOf(small) + String.valueOf(big))
						.split("");
				Arrays.sort(ar_str1);
				Arrays.sort(ar_str2);

				if (Arrays.equals(ar_str1, ar_str2)) {
					// 排序后比较,为真则找到一组
					// 返回两个Objects数组彼此相等,返回true
					sum++;
					System.out.println("第" + sum + "组: " + small + "*" + big
							+ "=" + product);
				}
				count++;
			}
		}
		System.out.println(count);
	}

	public void vampireArray2() {
		int small, big, product, floor = 10, ceil = 100;
		int from, count = 0, sum = 0;
		int[] ar_int1 = new int[4], ar_int2 = new int[4];
		for (small = floor; small < ceil; small++) {
			from = Math.max(1000 / small, small + 1);
			for (big = from; big < ceil; big++) {
				product = small * big;
				if (product % 100 == 0 || (product - small - big) % 9 != 0) {
					continue;
				}
				ar_int1[0] = small / 10;
				ar_int1[1] = small % 10;
				ar_int1[2] = big / 10;
				ar_int1[3] = big % 10;
				ar_int2[0] = product / 1000;
				product = product % 1000;
				ar_int2[1] = product / 100;
				product = product % 100;
				ar_int2[2] = product / 10;
				ar_int2[3] = product % 10;
				Arrays.sort(ar_int1);
				Arrays.sort(ar_int2);
				if (Arrays.equals(ar_int1, ar_int2)) {
					sum++;
					System.out.println("第" + sum + "组: " + small + "*" + big
							+ "=" + product);
				}
				count++;
			}
		}
		System.out.println(count);
	}

}

0 请登录后投票
   发表时间:2010-03-13  
ar_str1 = String.valueOf(i_val).split("");     
不理解,split不指定参考字符串,出来的结果是什么呢?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics