2023-05-01:给你一个整数 n , 请你在无限的整数序列 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...] 中找出并返回第 n 位上的数字。 1 <= n <=
Posted 在等月亮和你
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 <= 2^31 - 1。
输入:n = 11
输出:0
解释:第 11 位数字在序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... 里是 0 ,它是 10 的一部分。
答案2023-05-01:
该程序的大体过程:
1.定义数组 under
和 help
,分别用于存储数字位数对应能处理的数的个数和指示各位数之间的跨度。
2.实现函数 findNthDigit
,其输入为整数 n
,表示要查找的数字在整数序列中的位置。根据 under
数组,找到包含第 n 个数字的区间长度 len
,并返回调用子函数 number
的结果。
3.实现函数 number
,其输入为当前路径 path
、数字的位数 len
、最高位的权重 offset
、最低位的权重 all
和从开始算起剩余的第几个数字 nth
。如果 offset
等于 0,则说明已经到达最低位,直接返回路径经过的值中的第 nth
个数字;否则,计算出当前节点 cur
取值(这可能需要根据 offset
来进行特殊处理),根据 all
和 offset
计算下一个节点的路径 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.数组 under
和 help
的空间复杂度分别为 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;
[UOJ] #19 寻找道路
#19. 寻找道路NOIP2014
在有向图 GG 中,每条边的长度均为 11,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
- 路径上的所有点的出边所指向的点都直接或间接与终点连通。
- 在满足条件 1 的情况下使路径最短。
注意:图 GG 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入格式
第一行有两个用一个空格隔开的整数 nn 和 mm,表示图有 nn 个点和 mm 条边。
接下来的 mm 行每行 22 个整数 x,yx,y,之间用一个空格隔开,表示有一条边从点 xx 指向点yy。
最后一行有两个用一个空格隔开的整数 s,ts,t,表示起点为 ss,终点为 tt。
输出格式
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出−1−1。
样例一
input
3 2 1 2 2 1 1 3
output
-1
explanation
起点11与终点33不连通,所以满足题目描述的路径不存在,故输出−1−1。
样例二
input
6 6 1 2 1 3 2 6 2 5 4 5 3 4 1 5
output
3
explanation
注意点22不能在答案路径中,因为点22连了一条边到点66,而点66不与终点55连通。
限制与约定
对于30%的数据,0<n≤100<n≤10,0<m≤200<m≤20;
对于60%的数据,0<n≤1000<n≤100,0<m≤20000<m≤2000;
对于100%的数据,0<n≤100000<n≤10000,0<m≤2000000<m≤200000,0<x,y,s,t≤n0<x,y,s,t≤n,x,s≠tx,s≠t。
时间限制:1s1s
内存限制:128MB
分析
本来思路是 “反向存图+终点SPFA+额外判断” 求合法点集,然后 “起点SPFA” 求最短路。
结果一波挂残,20分 = =
后来决定用终点做根朴素DFS判断合法点集,再次20分 = =
关键在合法点集,根据样例合法点集内的点每一条出边都需要能到达终点,那么像样例2中的结点2是不能包括进合法点集的,此处需要注意实现部分。
代码
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define maxn 500000 5 using namespace std; 6 7 struct edge{ 8 int from,v; 9 }e[maxn],e1[maxn]; 10 11 const int inf = 999999999; 12 13 int n,m,a,b,que[maxn*100],head,tail,s,t,dis[maxn]; 14 bool book[maxn],chose[maxn]; 15 int tot,tot1,first[maxn],first1[maxn]; 16 void insert(int u,int v){ 17 tot++; 18 e[tot].from = first[u]; 19 e[tot].v = v; 20 first[u] = tot; 21 } 22 23 void insert1(int u,int v){ 24 tot1++; 25 e1[tot1].from = first1[u]; 26 e1[tot1].v = v; 27 first1[u] = tot1; 28 } 29 30 void dfs(int now){ 31 for(int i = first1[now];i;i = e1[i].from){ 32 int v = e1[i].v; 33 if(!book[v]){ 34 book[v] = true; 35 dfs(v); 36 } 37 } 38 } 39 40 void PRINT(){ 41 printf("#dis: "); 42 for(int i = 1;i <= n;i++) printf("%d ",dis[i]); 43 cout << endl; 44 } 45 46 void SPFA(){ 47 for(int i = 1;i <= n;i++) 48 book[i] = false,dis[i] = inf; 49 head = tail = 0; 50 que[head++] = s; 51 book[s] = true; 52 dis[s] = 0; 53 54 // PRINT(); 55 56 while(head > tail){ 57 int p = que[tail++]; 58 for(int i = first[p];i;i = e[i].from){ 59 int v = e[i].v; 60 if(dis[v] > dis[p]+1){ 61 dis[v] = dis[p]+1; 62 if(book[v]) continue; 63 book[v] = true; 64 que[head++] = v; 65 } 66 }book[p] = false; 67 } 68 69 // PRINT(); 70 71 if(dis[t] < inf) printf("%d",dis[t]); 72 else printf("-1"); 73 } 74 75 int main(){ 76 scanf("%d%d",&n,&m); 77 78 for(int i = 1;i <= m;i++){ 79 scanf("%d%d",&a,&b); 80 insert1(b,a); 81 } 82 83 scanf("%d%d",&s,&t); 84 85 book[t] = true; 86 dfs(t); 87 88 memset(chose,true,sizeof(chose)); 89 90 for(int i = 1;i <= n;i++){ 91 if(book[i]) continue; 92 for(int j = first1[i];j;j = e1[j].from){ 93 int v = e1[j].v; 94 if(!book[v] || !book[i]){ 95 chose[v] = false; 96 } 97 } 98 } 99 100 // cout << "----------------------------" << endl; 101 for(int i = 1;i <= n;i++){ 102 if(!chose[i]) continue; 103 for(int j = first1[i];j;j = e1[j].from){ 104 int v = e1[j].v; 105 if(chose[v]){ 106 // printf("%d %d\n",v,i); 107 insert(v,i); 108 } 109 } 110 } 111 112 // for(int i = 1;i <= n;i++){ 113 // printf("%c",chose[i]?‘T‘:‘F‘); 114 // printf("%c ",book[i]?‘T‘:‘F‘); 115 // } 116 117 SPFA(); 118 119 return 0; 120 }
以上是关于2023-05-01:给你一个整数 n , 请你在无限的整数序列 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...] 中找出并返回第 n 位上的数字。 1 <= n <=的主要内容,如果未能解决你的问题,请参考以下文章
2021-07-12:缺失的第一个正数。给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。比如[3,4,5
2022-10-15:给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。 你可以按 任意顺序 返回答案。 要求时间复杂度O(N)。 输入: nums = [1,1,1
Leetcode练习(Python):数组类:第41题:给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。你的算法的时间复杂度应为O(n),并且只能使用常数级别的额外空间。
2021-12-19:找到所有数组中消失的数字。 给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums(