有一个整数n,写一个函数f(n),返回0到n之间出现的"1"的个数

闲暇无事网上随便看看人家的技术博客,今天看到有个人出的算法题,捯饬好久总算搞定。
多说无益,show you my code!

 

 

package demo.algo;

/**
 * 求f(n):1..n中1出现的次数 f(1) = 1; f(10) = 2; f(13) = 6;
 * 
 * @author 
 * 归纳: f(9) = 1 
 * f(99) = 20 = 10 + 10 * f(9) 
 * f(999) = 300 = 100 + 10 * f(99) 
 * f(9999) = 4000 = 1000 + 10 * f(999) 
 * f(99999) = 50000 = 10000 + 10 * f(9999) 
 *          = f(0-09999) + f(20000-29999) + f(30000-39999) + f(40000-49999) 
 *          + f(50000-59999) + f(60000-69999) + f(70000-79999) + f(80000-89999) 
 *          + f(90000-99999) + f(10000-19999)
 *          = 9 * f(9999) + f(10000-19999)
 *          = 9 * f(9999) + 10000 + f(9999)
 *          = 10000 + 10 * f(9999)
 * f(7654321) = f(0-0999999) + f(1000000-1999999) + f(2000000-2999999)
 *              + f(3000000-3999999) + f(4000000-4999999) + f(5000000-5999999)
 *              + f(6000000-6999999) + f(7000000-7654321)
 *            = f(1000000 + 1999999) + 6 * f(999999) + f(654321)
 *            = 1000000 + 7 * f(999999) + f(654321)
 * f(1234567) = f(0-999999) + f(1000000-1234567)
 *            = f(99999) + 1234567 + 1 + f(234567)
 * 设g(n)=n的位数 g(123)=3 
 * t(n)=n的最高位数t(123)=1
 * r(n)=n除去最高位剩下的r(123)=23 
 * m(N)=f(99..9),9的个数为N个
 */
public class TotalOne {
    public static void main(String[] args) {
        System.out.println(t(123L));
        System.out.println(t(9876L));
        System.out.println(g(123L));
        System.out.println(g(9876L));
        System.out.println(r(123L));
        System.out.println(r(9876L));
        System.out.println(m(2L));
        System.out.println(m(3L));
        System.out.println(f(1L));
        System.out.println(f(7L));
        System.out.println(f(10L));
        System.out.println(f(11L));
        System.out.println(f(99L));
        System.out.println(f(999L));
        System.out.println(f(100000000L));        
    }

    //t(n)=n的最高位数t(123)=1
    private static Integer t(Long n) {
        return Integer.parseInt((String) n.toString().subSequence(0, 1));
    }

    //g(n)=n的位数 g(123)=3 
    private static Integer g(Long n) {
        return n.toString().length();
    }

    //r(n)=n除去最高位剩下的r(123)=23 r(7)=0
    private static long r(Long n) {
        if(n < 10){
            return 0;
        }
        return Long.parseLong((String) n.toString().subSequence(1, n.toString().length()));
    }

    //m(N)=f(99..9),9的个数为N个
    private static long m(long n) {
        if(n == 0){
            return 0L;
        }else {
            return (long) Math.pow(10, n - 1) + 10 * m(n - 1);
        }
    }

    private static long f(long n) {
        if(n == 0){
            return 0;
        }else if (t(n) > 1) {
            return (long) Math.pow(10, g(n) - 1) + t(n) * m(g(n) - 1) + f(r(n));
        } else {
            return m(g(n) - 1) + f(r(n)) + r(n) + 1;
        }
    }
}

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值