搜索算法的剪枝优化(Google笔试题)

来源:互联网 发布:思学通软件怎么样 编辑:程序博客网 时间:2024/05/21 03:58

这个题目的英文原题是:

Consider a function which, for a given whole number n, returns the number of ones required when writing out all numbers between 0 and n.

For example, f(13)=6. Notice that f(1)=1. What is the next largest n such that f(n)=n?

翻译过来大体是这样:
有一个整数n,写一个函数f(n),返回0到n之间出现的"1"的个数。比如f(13)=6,现在f(1)=1,问下一个最大的f(n)=n的n是什么?

为什么f(13)=6, 因为1,2,3,4,5,6,7,8,9,10,11,12,13.数数1的个数,正好是6.

---------------------------------------------------------------------------------------------------------------------------------

我的算法实现

import java.util.HashMap;
import java.util.Map;

/**
* @author Kevin
*/
public class CalculateNumberOfOnes {
    //存储已经检查过的符合条件的f(n)
    static Map treeNodeOKcache = new HashMap();
    private int currentSize = 0;
   
    //private int maxValue = Integer.MAX_VALUE;//2147483647
    private int maxTestValue = 40000000;

    public void getNextNum(int n){
       
        n = n<=1?1:n ;
       
        /*
        * 说明当前没有计算过
        */
        if(0 == currentSize){
            //f(1) = 1
            currentSize = 1;
            treeNodeOKcache.put(String.valueOf(1),String.valueOf(1));
        }
       
        /*
        * f(n+1) = f(n) + fs(n+1);
        * 计算本次fs(n+1)的结果
        */
        for(int i=2;i<maxTestValue;i++){
            currentSize += countOneNumber(i);
            if(currentSize == i){
                treeNodeOKcache.put(String.valueOf(i),String.valueOf(currentSize));
            }
        }
    }
   
    public int countOneNumber(int n){
        int count = 0;
        while ( n > 0 ){
        //模除10
        int mod = n%10;
        if ( mod == 1 )
            count++;
            n = n/10;
        }
        return count;
    }
   
    public static void main(String[] args){
        CalculateNumberOfOnes instance = new CalculateNumberOfOnes();
        long start = System.currentTimeMillis();
        instance.getNextNum(0);
        System.out.println("satisfy condition num is ="+treeNodeOKcache.size());
        System.out.println(" total spent "+(System.currentTimeMillis()-start)+"ms used!");
    }
   
}

结果:satisfy condition num is =40      total spent 12797ms used!

此题主要不是计算某一个f(n),而是利用f(n+1) = f(n) + fs(n+1) ;单算某一个数n效率很低,但是从0算到n时间的话速度就快了。再加上跳跃,还能更快。
真正在降低计算时间上作用巨大的是剪枝,也就是说如果把那么多数字看作一棵搜索树上的节点的话,如何知道哪些分支子树是不用去检查判断的,否则无论怎么做也快不起来。

----------------------------------------------------------------------------------------------------------------------

 

剪枝算法参考文章:
1、http://noi.gnzx.gd.cn/html/2004-11/105.htm

 

2、http://cai.csu.edu.cn/jpkc/rengongzhineng/rengongzhineng/kejian/AI/Ai/chapter3/333.htm

原创粉丝点击