首页 > 其他分享 >2023-05-01:给你一个整数 n , 请你在无限的整数序列 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...] 中找出并返回第 n 位上的数字。 1 <= n <=

2023-05-01:给你一个整数 n , 请你在无限的整数序列 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...] 中找出并返回第 n 位上的数字。 1 <= n <=

时间:2023-05-01 21:56:25浏览次数:49  
标签:11 10 help int under len nth 整数 offset

2023-05-01:给你一个整数 n ,
请你在无限的整数序列 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...]
中找出并返回第 n 位上的数字。
1 <= n <= 2^31 - 1。
输入:n = 11
输出:0
解释:第 11 位数字在序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... 里是 0 ,它是 10 的一部分。

答案2023-05-01:

该程序的大体过程:

1.定义数组 underhelp,分别用于存储数字位数对应能处理的数的个数和指示各位数之间的跨度。

2.实现函数 findNthDigit,其输入为整数 n,表示要查找的数字在整数序列中的位置。根据 under 数组,找到包含第 n 个数字的区间长度 len,并返回调用子函数 number 的结果。

3.实现函数 number,其输入为当前路径 path、数字的位数 len、最高位的权重 offset、最低位的权重 all 和从开始算起剩余的第几个数字 nth。如果 offset 等于 0,则说明已经到达最低位,直接返回路径经过的值中的第 nth 个数字;否则,计算出当前节点 cur 取值(这可能需要根据 offset 来进行特殊处理),根据 alloffset 计算下一个节点的路径 cur*(all/offset)+path,并递归地调用 number 函数。

4.在 main 函数中,定义一个整数变量 n 表示要查找的数字在整数序列中的位置,调用 findNthDigit 函数查找第 n 个数字,并输出结果。

时间复杂度和空间复杂度如下:

1.findNthDigit 函数中的循环需要遍历数组 under,时间复杂度为 O(1) 平均时间复杂度为 O(log n);
2. number 函数实现了一个递归结构,每次递归除去常数项的时间复杂度为 O(1), 递归深度为 O(log n),所以总时间复杂度为 O(log n);
3.数组 underhelp 的空间复杂度分别为 O(1),而递归调用 number 函数时,栈空间的最大使用量也为 O(log n)。因此,总的空间复杂度为 O(log n)。

综上所述,该算法的时间复杂度和空间复杂度均为 O(log n)。

go完整代码如下:

package main

var under = []int64{
	0, 9, 189, 2889, 38889, 488889, 5888889, 68888889, 788888889, 8888888889, 98888888889,
}

var help = []int{
	0,
	1,    // 1
	10,   // 2
	100,  // 3
	1000, // 4
	10000,
	100000,
	1000000,
	10000000,
	100000000,
	1000000000,
}

func findNthDigit(n int) int {
	l := 0
	for i := 1; i < len(under); i++ {
		if under[i] >= int64(n) {
			l = i
			break
		}
	}
	return number(0, l, help[l], help[l], n-int(under[l-1]))
}

// path : 路径 左(低) <- 右(高)
// len : n -> 5位数 len = 5 固定!
// offset : 10000 目前要决定的是高1位
// 1000 目前要决定的是高2位
// 10 目前要决定的是高2位
// 可变
// all : 10000 固定
// nth : 第几个
func number(path, len, offset, all, nth int) int {
	if offset == 0 {
		return (path / help[nth]) % 10
	} else {
		j := (nth - 1) / (len * offset)
		cur := 0
		if offset == all {
			cur = 1
		}
		cur += j
		return number(cur*(all/offset)+path, len, offset/10, all, nth-j*len*offset)
	}
}

func main() {
	n := 11
	digit := findNthDigit(n)
	println(n, "th digit is", digit)
}

在这里插入图片描述

rust完整代码如下:

static mut UNDER: [i64; 11] = [
    0,
    9,
    189,
    2889,
    38889,
    488889,
    5888889,
    68888889,
    788888889,
    8888888889,
    98888888889,
];
static mut HELP: [i32; 11] = [
    0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
];

fn find_nth_digit(n: i32) -> i32 {
    let under: &[i64; 11];
    let help: &[i32; 11];
    unsafe {
        under = &UNDER;
        help = &HELP;
    }

    let mut len = 0;
    for i in 1..under.len() {
        if under[i] >= n as i64 {
            len = i;
            break;
        }
    }

    number(0, len, help[len], help[len], (n - under[len - 1] as i32))
}

// path : 路径 左(低) <- 右(高)
// len : n -> 5位数 len = 5 固定!
// offset : 10000 目前要决定的是高1位
// 1000 目前要决定的是高2位
// 10 目前要决定的是高2位
// 可变
// all : 10000 固定
// nth : 第几个
fn number(path: i32, len: usize, offset: i32, all: i32, nth: i32) -> i32 {
    let help: &[i32; 11];
    unsafe {
        help = &HELP;
    }

    if offset == 0 {
        return (path / help[nth as usize]) % 10;
    } else {
        let j = (nth - 1) / (len as i32 * offset);
        let cur = if offset == all { 1 } else { 0 } + j;
        return number(
            cur * (all / offset) + path,
            len,
            offset / 10,
            all,
            nth - j * len as i32 * offset,
        );
    }
}

fn main() {
    unsafe {
        let n = 11;
        let digit = find_nth_digit(n);
        println!("{}th digit is {}", n, digit);
    }
}

在这里插入图片描述

c完整代码如下:

#include <stdio.h>

const long under[] = {
	0L,     // 0位数,一共能解决几个位
	9L,     // 1位数,一共能解决几个位
	189L,   // 1~2位数,一共能解决几个位
	2889L,  // 1~3位数,一共能解决几个位
	38889L,
	488889L,
	5888889L,
	68888889L,
	788888889L,
	8888888889L,
	98888888889L
};

const int help[] = {
	0,
	1,      // 1
	10,     // 2
	100,    // 3
	1000,   // 4
	10000,
	100000,
	1000000,
	10000000,
	100000000,
	1000000000
};

int findNthDigit(int n) {
	int len = 0;
	for (int i = 1; i < sizeof(under) / sizeof(long); i++) {
		if (under[i] >= n) {
			len = i;
			break;
		}
	}
	return number(0, len, help[len], help[len], n - under[len - 1]);
}

// path : 路径 左(低) <- 右(高)
// len : n -> 5位数 len = 5 固定!
// offset : 10000 目前要决定的是高1位
// 1000 目前要决定的是高2位
// 10 目前要决定的是高2位
// 可变
// all : 10000 固定
// nth : 第几个
int number(int path, int len, int offset, int all, int nth) {
	if (offset == 0) {
		return (path / help[nth]) % 10;
	}
	else {
		int j = (nth - 1) / (len * offset);
		int cur = (offset == all ? 1 : 0) + j;
		return number(cur * (all / offset) + path, len, offset / 10, all, nth - j * len * offset);
	}
}

int main() {
	int n = 11;
	int digit = findNthDigit(n);
	printf("%dth digit is %d\n", n, digit);
	return 0;
}

在这里插入图片描述

c++完整代码如下:

#include <iostream>
using namespace std;

const long under[] = {
	0L,     // 0位数,一共能解决几个位
	9L,     // 1位数,一共能解决几个位
	189L,   // 1~2位数,一共能解决几个位
	2889L,  // 1~3位数,一共能解决几个位
	38889L,
	488889L,
	5888889L,
	68888889L,
	788888889L,
	8888888889L,
	98888888889L
};

const int help[] = {
	0,
	1,      // 1
	10,     // 2
	100,    // 3
	1000,   // 4
	10000,
	100000,
	1000000,
	10000000,
	100000000,
	1000000000
};

// path : 路径 左(低) <- 右(高)
// len : n -> 5位数 len = 5 固定!
// offset : 10000 目前要决定的是高1位
// 1000 目前要决定的是高2位
// 10 目前要决定的是高2位
// 可变
// all : 10000 固定
// nth : 第几个
int number(int path, int len, int offset, int all, int nth) {
	if (offset == 0) {
		return (path / help[nth]) % 10;
	}
	else {
		int j = (nth - 1) / (len * offset);
		int cur = (offset == all ? 1 : 0) + j;
		return number(cur * (all / offset) + path, len, offset / 10, all, nth - j * len * offset);
	}
}

int findNthDigit(int n) {
	int len = 0;
	for (int i = 1; i < sizeof(under) / sizeof(long); i++) {
		if (under[i] >= n) {
			len = i;
			break;
		}
	}
	return number(0, len, help[len], help[len], n - under[len - 1]);
}

int main() {
	int n = 11;
	int digit = findNthDigit(n);
	cout << n << "th digit is " << digit << endl;
	return 0;
}

在这里插入图片描述

标签:11,10,help,int,under,len,nth,整数,offset
From: https://www.cnblogs.com/waitmoon/p/17367063.html

相关文章

  • win10 强制删除 “文件夹或文件已在另一程序中打开”中的文件
    今天遇到一个文件夹,右键删除删不掉,提示“文件夹已在另一程序中打开”,但这个文件夹确实是没有用的,里面的文件也没用。于是我使用360强制删除也不行,使用winrar压缩后删除也不行。最后使用了git解决。具体方法:win10安装git,使用gitbash命令行,切换到要删除的文件夹所在的目录,用......
  • AtCoder Regular Contest 119 E Pancakes
    洛谷传送门AtCoder传送门感觉挺典的,为啥有2500啊(观察发现,反转序列对\(\sum\limits_{i=1}^{n-1}|a'_i-a'_{i+1}|\)影响不大。具体而言,设反转了\(a_l\sima_r\),记\(s=\sum\limits_{i=1}^{n-1}|a_i-a_{i+1}|\),那么\(s'=s-|a_{l-1}-a_l|-|a_r-a_{r+1}|......
  • 2023冲刺清北营10
    关于闲话如果写学术性闲话确实没有必要。(毕竟几乎每天都在写题解)但如果写别的内容可能大家也不会有太大的兴趣,因为可以用于聊的兴趣就是二次元了,但是现在机房里真正以二次元为爱好的人并不多。(如果真正写闲话可能会变成补番指南)T1九转大肠考虑进行dp,设\(f_{i,j,k}\)表示......
  • 7-011-(LeetCode- 337) 打家劫舍Ⅲ
    1.题目读题 考查点 2.解法思路 代码逻辑 具体实现113.总结......
  • 7-010-(LeetCode- 322) 零钱兑换
    1.题目读题 考查点 2.解法思路 代码逻辑 具体实现113.总结......
  • Codeforces Gym 103439D - LIS Counting(猜结论+状压)
    一道需要一些猜结论技巧的中档题。首先突破口在于排列长度恰好等于不是额外输入的某个数\(k\)而是LDS与LIS的乘积,这显然启示我们去找一些性质。根据dilworth定理,最长反链等于最小链覆盖,故LIS的长度,就是最少需要的递减数列的个数使得每个元素被覆盖至少一次,而每个递减数......
  • 10分钟搞定!C++类中构造函数和析构函数的完全指南
    一、初步认识构造函数1.什么是构造函数?要了解构造函数就要先了解一下,类的6个默认成员函数,如下图:构造函数:构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有一个合适的初始值,并且在对象整个生命周期内只调用一次。通俗一点来......
  • PMP-11-项目经理的通用技能
    1.一个完整的产品生命周期包括概念-计划-开发-验证-发布-运行维护等6个阶段2.通常,产品生命周期要远远长于项目生命周期3.一个完整的项目生命周期可以划分为启动项目、组织与准备、执行工作、结束项目等4个阶段4.项目生命周期的一个重要特征是,项目前期投入资源很少,在执行工作阶......
  • PMP-10-项目经理的通用技能
    项目经理这4个能力是最重要的了:一要有大局观,能够站在凌驾于不同相关方之上的角度,去分析怎么协调项目工作,能达到最好的效果。二要有清晰坚定的目标,坚信自己做的事情一定能成功。三要有换位思考的能力,能够站在别人的角度去思考自己的项目,做出有利于所有人的决策。四要有强大的执......
  • n5105软路由 跑分
    鲁大师新版  ......