【算法】剑指offer

1,从1到整数n中1出现的次数

思路:若百位上数字为0,百位上可能出现1的次数由更高位决定;若百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响;若百位上数字大于1,则百位上出现1的情况仅由更高位决定。
举例:
①534
这里写图片描述
个位1出现的次数:round*1+1 (每次循环1出现一次,0-9循环了53次,第54次循环为0-4)
这里写图片描述
十位1出现的次数:round*10 + 10(每次循环1出现10次,0-9循环了round=5次,第六次循环为0-3)
其他高位循环同理。
故有:

534 = (个位1出现次数)+(十位1出现次数)+(百位1出现次数)
    =(53*1+1) +(5*10+10)+(0*100+100) = 214
530 = (53*1)  +(5*10+10)+(0*100+100) = 213
504 = (50*1+1)+(5*10)   +(0*100+100) = 201
514 = (51*1+1)+(5*10+4+1)+(0*100+100) = 207
10  =  (1*1) + (0*10+0+1) = 2

代码如下:

public long CountOne(int n) {
        int count = 0; // 1的个数
        int i = 1; // 当前位
        int current = 0, after = 0, before = 0;
        while ((n / i) != 0) {
            before = n / (i * 10); // 高位
            current = (n / i) % 10; // 当前位
            after = n - (n / i) * i; // 低位
            if (current == 0)
                //如果为0,出现1的次数由高位决定,等于高位数字 * 当前位数
                count = count + before * i;
            else if (current == 1)
                //如果为1,出现1的次数由高位和低位决定,高位*当前位+低位+1
                count = count + before * i + after + 1;
            else if (current > 1)
                // 如果大于1,出现1的次数由高位决定,(高位数字+1)* 当前位数
                count = count + (before + 1) * i;
            //前移一位
            i = i * 10;
        }
        return count;
    }

2,丑数

丑数是只包含因子2、3和5的数,求从小到大的第N个丑数。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

思路一:
丑数判断:

 boolean isUgly(int number) {
        while (number % 2 == 0) number /= 2;
        while (number % 3 == 0) number /= 3;
        while (number % 5 == 0) number /= 5;
        return number == 1 ? true : false;
    }

然后依次输入每个数就可以获得N个丑数。但这样计算太多,即使一个数不是丑数,也要进行多次计算。
思路二:空间换时间,创建数组存储已经找到的丑数。后序的丑数都是min乘2或3或5得到的。
初始化数组只:{1} ;min = 1,后序 乘2或3或5,之后比较取最小值:2,3,5

    public int GetUglyNumber_Solution(int index) {
        if (index <= 0)
            return 0;
        int[] arr = new int[index];
        arr[0] = 1;
        int multiply2 = 0;
        int multiply3 = 0;
        int multiply5 = 0;
        for (int i = 1; i < index; i++) {
            int min = Math.min(arr[multiply2] * 2, Math.min(arr[multiply3] * 3, arr[multiply5] * 5));
            arr[i] = min;
            if (arr[multiply2] * 2 == min)
                multiply2++;
            if (arr[multiply3] * 3 == min)
                multiply3++;
            if (arr[multiply5] * 5 == min)
                multiply5++;
        }
        return arr[index - 1];
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值