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.定义数组 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;


[UOJ] #19 寻找道路

#19. 寻找道路NOIP2014

 

在有向图 GG 中,每条边的长度均为 11,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:

  1. 路径上的所有点的出边所指向的点都直接或间接与终点连通。
  2. 在满足条件 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<n100<n≤10,0<m200<m≤20;

对于60%的数据,0<n1000<n≤100,0<m20000<m≤2000;

对于100%的数据,0<n100000<n≤10000,0<m2000000<m≤200000,0<x,y,s,tn0<x,y,s,t≤n,x,stx,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 <=的主要内容,如果未能解决你的问题,请参考以下文章

346给你一个整数 n ,请你判断 n 是否为 丑数

346给你一个整数 n ,请你判断 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(