算法-数位递增的数

问题概述


题目:算法-数位递增的数-

问题描述:
一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的数,
例如1135是一个数位递增的数,而1024不是一个数位递增的数.
给定正整数 n,请问在整数 1 至 n 中有多少个数位递增的数?

输入:
输入的第一行包含一个整数 n。
输出:
输出一行包含一个整数,表示答案。
样例输入:
30
样例输出:
26


1. 问题分析


1.1 算法核心

这是一道初级算法题,较为容易,算法核心点在于对于整形数的认识,快速解出题目是我们的终极目标;


1.2 算法分析

虽然这是一道初级算法题,但是有很多进阶的算法题类似整形数问题都是由此演变而来的,注重底层细节是我们写算法的程序猿必不可少的素质;
而本题最重要的底层细节就是整形数的处理,一般我们会想到利用C++的STL容器string字符串类对象去解决,即下面解决方案的第一个声明函数checkIncreaseByString,从字符串尾开始向前比较,只要有一个不符合递增规律就说明不满足题意直接返回false即可,表示这个整形数不是数位递增的数,如果正常退出比较循环说明这是一个数位递增的数,返回true表示,然后相应的让我们预先定义的计数器+1就行,最后按照题目要求输出即可;
需要注意的点就是这类整形数题目有多种解决方法,可以利用字符串string类对象的函数,也可以利用数学计算的特点,比如求余运算等对整形数做处理。针对这两种方法呢,我进行了性能测试,最后发现利用string类对象的方法性能较差,性能上两者至少差了10倍,这也启示我们类虽然解决了代码复用的问题,封装了很多函数属性等,给我们程序猿带来很大便利,但很多优秀的算法的核心其实是依靠的程序猿的思维过程,一个程序猿很熟悉底层细节,那么他就能设计出一个针对某个问题效率很高的算法,这一点是母庸质疑的!


2. 解决方案

#include <iostream>
#include <string>
using namespace std;

bool checkIncreaseByString(int t);
bool checkIncreaseByInteger(int t);

int main()
{
	int ans = 0, n;

	scanf("%d", &n);
	for(int i = 1; i <= n; i++)
		//if(checkIncreaseByString(i)) ans++;
		if(checkIncreaseByInteger(i)) ans++;
	printf("%d\n", ans);

	return 0;
}

bool checkIncreaseByString(int t)
{
	char temp[8];

	sprintf(temp, "%d", t);
	string s(temp);
	for(int i = 1; i < s.size(); i++)
		if(s[i - 1] > s[i]) return false;

	return true;
}

bool checkIncreaseByInteger(int t)
{
	int t1 = t % 10;
	int t2;

	t /= 10;
	while(t)
	{
		t2 = t % 10;
		if(t1 < t2)
			return false;
		t1 = t2;
		t /= 10;
	}

	return true;
}

3. 资源分享

旗木白哉のGitHub:
https://github.com/YangMengHeng
C++ / C源代码下载地址:
https://github.com/YangMengHeng/myCode/tree/master/VSCode
Java源代码下载地址:
https://github.com/YangMengHeng/myCode/tree/master/Java
旗木白哉のblog源代码下载地址:
https://github.com/YangMengHeng/myCode/tree/master/%E6%97%97%E6%9C%A8%E7%99%BD%E5%93%89%E3%81%AEblog


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值