小米oj第23题,找到第 N 个数字 II

//by wyz
#include <stdio.h>
#include "math.h"

//获取到第i行字符串的长度
long long Get_Line(long long i)
{
	long long sum = 0,pow_num = 0,m = i,min = 0;
	while ((m /= 10) > 0)
	{
		pow_num++;
	}

	for (int j = 0; j < pow_num; j++)
	{
		sum += 9 *(j+1)*pow(10, j);
		min += 9 * pow(10, j);
	}

	sum += (pow_num + 1)*(i-min);
	return sum;
}

//获取第1到第i行字符串加起来的长度
long long Get_Sum(long long i)
{
	long long j = i,Pow_Num = 0,Sum = 0;
	while ((j /= 10) > 0)
	{
		Pow_Num++;
		Sum += (pow(10, Pow_Num) - 1-(pow(10, Pow_Num-1) - 1))*
			(Get_Line(pow(10, Pow_Num-1))+ Get_Line(pow(10, Pow_Num) - 1))/2;
	}
		return Sum += (i-pow(10, Pow_Num) + 1)*
			(Get_Line(pow(10, Pow_Num )) + Get_Line(i)) / 2;
}

int main()
{
	long long i,len = 0, Remain,Index = 0,Sub_Index = 0, N = 101, Left_Index = 1, Right_Index = 1;
	char buf[25] = "";
	scanf("%lld", &N);

	Index = 1;
	//找到大致范围
	while (Get_Sum(Index) < N)
	{
		Index *= 2;
	}

	Left_Index = Index / 2;
	Right_Index = Index;
	//根据上一步结果,使用二分法精确找到第N个字符所在字符串行数
	while (1)
	{
		len = Get_Sum((Left_Index + Right_Index) / 2);
		if (len < N)
		{
			Left_Index = (Left_Index + Right_Index) / 2;
		}
		else if (len > N)
		{
			Right_Index = (Left_Index + Right_Index) / 2;
		}
		else
		{
			Index = (Left_Index + Right_Index) / 2;
			break;
		}
		if (Left_Index + 1 == Right_Index)
		{
			if (Get_Sum(Left_Index) == N)
			{
				Index = Left_Index;
			}
			else
			{
				Index = Right_Index;
			}
			break;
		}
	}
	Left_Index = 1;
	Right_Index = Index;

	//获取到第N个数字在这一列中的偏移
	Remain = Get_Line(Index) - Get_Sum(Index) + N;
	//根据偏移获取到第N位属于哪一个数字
	while (1)
	{
		len = Get_Line((Left_Index + Right_Index) / 2);
		if (len < Remain)
		{
			Left_Index = (Left_Index + Right_Index) / 2;
		}
		else if (len > Remain)
		{
			Right_Index = (Left_Index + Right_Index) / 2;
		}
		else
		{
			Sub_Index = (Left_Index + Right_Index) / 2;
			break;
		}
		if (Left_Index + 1 == Right_Index)
		{
			if (Get_Line(Left_Index) == Remain)
			{
				Sub_Index = Left_Index;
			}
			else
			{
				Sub_Index = Right_Index;
			}

			break;
		}
	}

	//printf("%lld\t%lld\t%lld\t%lld\t",Index, Get_Sum(Index-1),N, Get_Sum(Index));
	//printf("%lld\t%lld\n", Remain - Get_Line(Sub_Index - 1), Sub_Index);

	//将这个数字转化为字符串后显示出来
	sprintf(buf, "%lld", Sub_Index);
	//Get_Line(Sub_Index - 1)是上一行的长度,这样可以算出来N是最后一个数字的第几位。
	printf("%c", buf[Remain - Get_Line(Sub_Index - 1) - 1]);

}

效率应该还行,c写的是100%,直接拿去c++也是100%。

 

          

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值