网易雷火3.17 人工智能研究员(NLP方向)笔试题:两道算法题都是Leetcode原题。(Leetcode) 440 && 845)
再做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*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;
}
};
题目链接: https://leetcode.com/problems/k-th-smallest-in-lexicographical-order/
输入正整数n, k,n >= k, 找出[1,n]范围内按照字典排序的最小第k个值。
输入描述:
输入两个正整数n,k
输出描述:
一个正整数
示例:
输入
15, 3
输出
11
题意:题意其实其实很明确,就是给你一个数n,输出字典序最小的第k个值;如果之前对字典序不是很熟悉的话,这道题会没什么思路,可以先做一下Leetcode 386,可以说是这道题的基础了。
做完386之后,就会有一个这样的想法,直接拿386的结果输出不就行了吗?事实证明那样做会超时。
可以当成10叉树来处理,先序遍历10叉树的结果就是字典序。但是这里可以借用这种思想,不用真正实现一个10叉树。
思路:
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){
int steps = caldistance(n, cur, cur+1);
if(steps <= k){
cur += 1;
k -= steps;
}else{
cur *= 10; //10叉树的子节点
k -= 1;
}
}
return cur;
}
//计算n1和n2之间的节点数
int caldistance(int n,long long n1, long long n2){
int steps = 0;
while(n1 <= n){
steps += min((long long)(n+1), n2) - n1;
n1 *= 10;
n2 *= 10;
}
return steps;
}
};
同样的做845之前,我们也可以先做1道简单点的练练手,821的方法也和845用的方法类似。
Given a string S and a character C, return an array of integers representing the shortest distance from the character C in the string.
Example 1:
Input: S = “loveleetcode”, C = ‘e’
Output: [3, 2, 1, 0, 1, 0, 0, 1, 2, 2, 1, 0]
Note:
S string length is in [1, 10000].
C is a single character, and guaranteed to be in string S.
All letters in S and C are lowercase.
这道题比较简单,有多种方法可以做,这里推荐2-pass,用一个数组存储最小距离,前后遍历各遍历一次,更新最小距离。
代码如下:
class Solution{
public:
vector<int> shortestToChar(string S, char C) {
int n = S.length(),pos = -n;
vector<int> res(n,n); // 存储
for(int i=0; i<n; i++){
if(S[i] == C) pos = i; //记录当前C的位置
res[i] = min(res[i], abs(i - pos));
}
for(int i=n-1; i>=0; i--){
if(S[i] == C) pos = i;
res[i] = min(res[i], abs(i-pos));
}
return res;
}
};
下面这种写法可能更好理解一些,首先先找到所有的C的位置,然后再计算其他点到C的距离。
class Solution {
public:
vector<int> shortestToChar(string S, char C) {
int n = S.length();
vector<int> res(n,n);
for(int i=0; i<n; i++){
if(S[i] == C)
res[i] = 0; //将所有C的位置标记为0
}
for(int i=1; i<n; i++){
res[i] = min(res[i], res[i-1]+1); //更新距离
}
for(int i=n-2; i>=0; i--){
res[i] = min(res[i], res[i+1]+1);
}
return res;
}
};
给定一个数组,代表海拔高度,输出最长连续山脉的长度。以山脉M为例,要求:
1.M.length >= 3
, 如果不存在则输出0;
2.存在0, 使得
M[0]<...
。...>M[M.length-1]
输入描述:
一系列非负整数
输出描述:
非负整数
示例:
输入
2,1,7,2,5
输出
3
845也可以用821那种方法,分为两个阶段,山脉的上升阶段和下降阶段,分别用两个数组分别存储上升阶段和下降阶段,然后更新上升阶段,下降阶段和的最大值。
class Solution {
public:
int longestMountain(vector<int>& A) {
int n = A.size(), res = 0;
vector<int> up(n,0),down(n,0);
for(int i=0; i < n; i++){
if(i > 0 && A[i] > A[i-1]) up[i] = up[i-1] + 1; //上升过程
}
for(int i=n-2; i>=0; i--){
if(A[i] > A[i+1]) down[i] = down[i+1] + 1; //下降过程
if(down[i] && up[i])
res = max(res, down[i] + up[i] + 1);
}
return res;
}
};
//不使用额外内存
class Solution{
public:
int longestMountain(vector<int>& A) {
int res = 0, down = 0, up = 0;
for(int i=1; i<A.size(); i++){
if(down && A[i] > A[i-1] || A[i-1] == A[i]) //山脉结束条件
up = down = 0;
down += A[i-1] > A[i];
up += A[i] > A[i-1];
if(down && up)
res = max(res, down + up + 1);
}
return res;
}
};
也可以使用双指针法:
class Solution{
public:
int longestMountain(vector<int>& A) {
int n = A.size(), down = 0 ,up = 0, res = 0;
while(up < n-1){
while(up < n-1 && A[up] >= A[up+1]){ //跳过不是山脉的情况
up++;
}
down = up; // 起点
while(down<n-1 && A[down] < A[down+1]){
down++; // 上升阶段
}
while(down<n-1 && A[down] > A[down+1]){
down++; //下降阶段
res = max(res, down - up + 1);
}
up = down; // 更新起点
}
return res;
}
};
更多代码可以查看Github