网易雷火3.17 人工智能研究员(NLP方向)笔试题:两道算法题都是Leetcode原题。(Leetcode) 440 && 845)
LeetCode 386:
再做440之前,可以先做做386;可以算是440的基础题。
题目描述:
Given an integer n, return 1 - n in lexicographical order.
For example, given 13, return: [1,10,11,12,13,2,3,4,5,6,7,8,9].
Please optimize your algorithm to use less time and space. The input size may be as large as 5,000,000.
题解:
题意其实和440是差不多的,给你一个数n,返回一个字典序的数组。
从给的样例推测出字典序是怎么定义的:
- 一个数x,如果
x*10 < n
, 那么x后就是x*10
。 - 如果
x*10 >= n
, 那么x后接的就是x+1,这里需要注意的需要进位的情况,假如x=19,n= 21,它后面接的应该是2。
下面看看代码:
class Solution {
public:
vector<int> lexicalOrder(int n) {
vector<int> res;
int cur = 1;
for(int i=1; i<=n; i++){
res.push_back(cur);
if(cur * 10 <= n){
cur *= 10;
}else{
if(cur >= n){
cur /= 10;
}
cur += 1;
while(cur % 10 == 0){
cur /= 10; // 对进位进行处理
}
}
}
return res;
}
};
Leetcode 440:
题目链接: https://leetcode.com/problems/k-th-smallest-in-lexicographical-order/
1.题目描述:
输入正整数n, k,n >= k, 找出[1,n]范围内按照字典排序的最小第k个值。
输入描述:
输入两个正整数n,k
输出描述:
一个正整数
示例:
输入
15, 3
输出
11
2.题解:
题意:题意其实其实很明确,就是给你一个数n,输出字典序最小的第k个值;如果之前对字典序不是很熟悉的话,这道题会没什么思路,可以先做一下Leetcode 386,可以说是这道题的基础了。
做完386之后,就会有一个这样的想法,直接拿386的结果输出不就行了吗?事实证明那样做会超时。
可以当成10叉树来处理,先序遍历10叉树的结果就是字典序。但是这里可以借用这种思想,不用真正实现一个10叉树。
思路:
- 假如我们从cur节点开始遍历,其实我们只需知道从cur到cur+1节点之间经历了多少节点,如果经历的节点<=k, 那我们再从cur+1往后遍历,k= k-经历的节点。
- 如果经历的节点数>k, 说明第k个节点就在cur,cur+1之后,我们就把cur*10(cur的第一个子节点),继续往后遍历。
- 怎么计算cur到cur+1 之间经历的节点数量呢?假设
n1=cur
,n2=cur+1
,n2总是n1最右子节点之后的右节点。 - 如果
n2<=n
,它们之间的节点数为n2 - n1, 如果n2>n
,说明最大节点n在n1到n2之间,它们的节点数为n+1-n1;然后n110,n210往后遍历。
代码如下:
class Solution {
public:
int findKthNumber(int n, int k) {
long long cur = 1;
k = k - 1;
while(k > 0){