剑指offer(31~33)从1 到 n 中1出现的次数--把数组排成最小的数--丑数

从1 到 n 中1出现的次数

求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

class Solution {
public:
	int NumberOf1Between1AndN_Solution(int n)
	{
		int ret = 0;
		for (int i = 1; i <= n; i++)
		{
			int num = i;
			while (num)
			{
				if (num % 10 == 1)
					ret++;
				num = num / 10;
			}
		}
		return ret;
	}
};

牛客网链接

把数组排成最小的数

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

解题思路: 先将整型数组转换成String数组,然后将String数组排序,最后将排好序的字符串数组拼接出来。关键就是制定排序规则。

  • 排序规则如下,
    假如有元素a和元素b,若ab > ba 则 a应该处于b之后;若ab < ba 则a应该处于b之前;若ab = ba 则 a = b;解释说明:比如 “3” 和 "31"比较谁先谁后, “331” > “313”,‘31’应该处于‘3’之前。
class Solution {
public:
    string PrintMinNumber(vector<int> numbers) {
        string res ="";
        sort(numbers.begin(),numbers.end(),cmp);
        for(int i=0;i<numbers.size();i++){
            res += to_string(numbers[i]);
        }
        return res;
    }
    static bool cmp(int a,int b){
        string sa = "";
        string sb = "";
        sa += to_string(a);
        sa += to_string(b);
        sb += to_string(b);
        sb += to_string(a);
        return sa<sb;
    }
};

牛客网链接

丑数

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

思路

我们规定了只包含质因子2,3,5的是丑数,也就是说,一个数可以由有限个2 和有限个3 和有限个5相乘的来,换言之,这个数可以最后分解成 n 1 n1 n1个2, n 2 n2 n2个3, n 3 n3 n3个5组成,我们还知道 1 是最小的丑数。那么如何从1推出下一个丑数呢。我们在列举几个丑数观察。

1 , 1*2, 1*3, 2*2, 1*5, 2*3 ,3*2,4*2, 3*3 ...

我们发现每个数,都可以由前面某个数 ×2 或者 ×3 或者 ×5得到,即这些数按升序插入到这个数组。
代码实现:

class Solution {
public:
    int GetMin(int a,int b,int c)
    {
        if(a < b)
            return a < c ? a : c;
        else 
            return b < c ? b : c;
    }
    int GetUglyNumber_Solution(int index) {
        if(index < 0)
            return -1;
        int pos2 = 1,pos3 = 1,pos5 = 1;
        int* arr = new int[index + 1];
        arr[1] = 1;
        for(int i=2;i <= index;i++)
        {
            arr[i] = GetMin(arr[pos2]*2,arr[pos3]*3,arr[pos5]*5);
            if(arr[pos2]*2 <= arr[i])
                pos2++;
            if(arr[pos3]*3 <= arr[i])
                pos3++;
            if(arr[pos5]*5 <= arr[i])
                pos5++;
        }
        return arr[index];
    }
};

牛客网链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值