386. 字典序排数
2022.4.18 每日一题,毕业时间突然提前一个月,懵了…
题目描述
给你一个整数 n ,按字典序返回范围 [1, n] 内所有整数。
你必须设计一个时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。
示例 1:
输入:n = 13
输出:[1,10,11,12,13,2,3,4,5,6,7,8,9]
示例 2:
输入:n = 2
输出:[1,2]
提示:
1 <= n <= 5 * 10^4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lexicographical-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
class Solution {
public List<Integer> lexicalOrder(int n) {
//和前几天那个题差不多,不过这个好像简单点
//直接往后面加就可以了,如果不可以那跳回上一层
//1 后面加 0,变成10,如果小于n,那么说明还能加,就变成100,大于n了就返回上一层,也就是当前数除以10
//就变成了10,然后加1变成11
List<Integer> res = new ArrayList<>();
int idx = 1;
res.add(idx);
while(res.size() < n){
//先往后边延生
if(idx * 10 <= n){
idx *= 10;
//但是加1可能超过范围,例如999 + 1 = 1000
}else{
while(idx % 10 == 9 || idx + 1 > n){
idx /= 10;
}
idx++;
}
res.add(idx);
}
return res;
}
}
dfs
class Solution {
List<Integer> res = new ArrayList<>();
public List<Integer> lexicalOrder(int n) {
for(int i = 1; i < 10; i++){
dfs(i, n);
}
return res;
}
public void dfs(int num, int n){
if(num > n)
return;
res.add(num);
//向下一层扩展
for(int i = 0; i < 10; i++){
dfs(num * 10 + i, n);
}
}
}
821. 字符的最短距离
2022.4.19 每日一题
题目描述
给你一个字符串 s 和一个字符 c ,且 c 是 s 中出现过的字符。
返回一个整数数组 answer ,其中 answer.length == s.length 且 answer[i] 是 s 中从下标 i 到离它 最近 的字符 c 的 距离 。
两个下标 i 和 j 之间的 距离 为 abs(i - j) ,其中 abs 是绝对值函数。
示例 1:
输入:s = “loveleetcode”, c = “e”
输出:[3,2,1,0,1,0,0,1,2,2,1,0]
解释:字符 ‘e’ 出现在下标 3、5、6 和 11 处(下标从 0 开始计数)。
距下标 0 最近的 ‘e’ 出现在下标 3 ,所以距离为 abs(0 - 3) = 3 。
距下标 1 最近的 ‘e’ 出现在下标 3 ,所以距离为 abs(1 - 3) = 2 。
对于下标 4 ,出现在下标 3 和下标 5 处的 ‘e’ 都离它最近,但距离是一样的 abs(4 - 3) == abs(4 - 5) = 1 。
距下标 8 最近的 ‘e’ 出现在下标 6 ,所以距离为 abs(8 - 6) = 2 。
示例 2:
输入:s = “aaab”, c = “b”
输出:[3,2,1,0]
提示:
1 <= s.length <= 10^4
s[i] 和 c 均为小写英文字母
题目数据保证 c 在 s 中至少出现一次
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-distance-to-a-character
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
我这里先记录每个c的位置,然后和每一个字符位置做比较
class Solution {
public int[] shortestToChar(String s, char c) {
//先统计每个字符的位置,然后对于每一个字符,找位置
int l = s.length();
List<Integer> list = new ArrayList<>();
for(int i = 0; i < l; i++){
char temp = s.charAt(i);
if(temp == c)
list.add(i);
}
int[] res = new int[l];
int idx = 1;
int idx1 = list.get(0);
int idx2 = list.size() > 1 ? list.get(1) : 100000;
for(int i = 0; i < l; i++){
if(i <= idx1){
res[i] = idx1 - i;
}else if(i > idx1 && i < idx2){
res[i] = Math.min(i - idx1, idx2 - i);
}else{
res[i] = 0;
idx1 = idx2;
idx2 = list.size() > ++idx ? list.get(idx) : 100000;
}
}
return res;
}
}
题解这种两次遍历更加简洁
注意python这个倒序输出需要反着写顺序,并且第三个参数必须得写,否则默认是正序的,即使写range(l-1, -1)也不行;另外,不取上限同样
class Solution:
def shortestToChar(self, s: str, c: str) -> List[int]:
l = len(s)
res = [0] * l
idx = -l
for i, ch in enumerate(s):
if ch == c:
idx = i
res[i] = i - idx
idx = 2 * l
for i in range(l - 1, -1, -1):
if s[i] == c:
idx = i
res[i] = min(idx - i, res[i])
return res
388. 文件的最长绝对路径
2022.4.20 每日一题,谷雨,春季的最后一个节气,马上立夏了
题目描述
假设有一个同时存储文件和目录的文件系统。下图展示了文件系统的一个示例:
这里将 dir 作为根目录中的唯一目录。dir 包含两个子目录 subdir1 和 subdir2 。subdir1 包含文件 file1.ext 和子目录 subsubdir1;subdir2 包含子目录 subsubdir2,该子目录下包含文件 file2.ext 。
在文本格式中,如下所示(⟶表示制表符):
dir
⟶ subdir1
⟶ ⟶ file1.ext
⟶ ⟶ subsubdir1
⟶ subdir2
⟶ ⟶ subsubdir2
⟶ ⟶ ⟶ file2.ext
如果是代码表示,上面的文件系统可以写为 “dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext” 。‘\n’ 和 ‘\t’ 分别是换行符和制表符。
文件系统中的每个文件和文件夹都有一个唯一的 绝对路径 ,即必须打开才能到达文件/目录所在位置的目录顺序,所有路径用 ‘/’ 连接。上面例子中,指向 file2.ext 的 绝对路径 是 “dir/subdir2/subsubdir2/file2.ext” 。每个目录名由字母、数字和/或空格组成,每个文件名遵循 name.extension 的格式,其中 name 和 extension由字母、数字和/或空格组成。
给定一个以上述格式表示文件系统的字符串 input ,返回文件系统中 指向 文件 的 最长绝对路径 的长度 。 如果系统中没有文件,返回 0。
示例 1:
输入:input = “dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext”
输出:20
解释:只有一个文件,绝对路径为 “dir/subdir2/file.ext” ,路径长度 20
示例 2:
输入:input = “dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext”
输出:32
解释:存在两个文件:
“dir/subdir1/file1.ext” ,路径长度 21
“dir/subdir2/subsubdir2/file2.ext” ,路径长度 32
返回 32 ,因为这是最长的路径
示例 3:
输入:input = “a”
输出:0
解释:不存在任何文件
示例 4:
输入:input = “file1.txt\nfile2.txt\nlongfile.txt”
输出:12
解释:根目录下有 3 个文件。
因为根目录中任何东西的绝对路径只是名称本身,所以答案是 “longfile.txt” ,路径长度为 12
提示:
1 <= input.length <= 10^4
input 可能包含小写或大写的英文字母,一个换行符 ‘\n’,一个制表符 ‘\t’,一个点 ‘.’,一个空格 ’ ',和数字。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-absolute-file-path
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
最近每日一题出了很多个这种题,栈还是很容易想到的
我这个主要卡住的点就是,我以为字符串中的\n,\t是两个字符,结果去取\判断,导致一直不知道哪里错了,改了以后就过了
class Solution {
public int lengthLongestPath(String input) {
//栈的那种结构,先放入文件夹,再放文件
//栈中存放一个【int,int,int】的结构,表示第几级目录,当前路径长度
//遇到字母或者数字空格,进行字符串的拼接;如果是点,那么进行特殊标记
//遇到\,看如果下一个是n,那么先处理当前文件,如果是文件,那么统计长度,如果是文件夹,那么放入栈中
//然后新建一个点
//如果下一个是t,那么给当前数据结构级别加1
int l = input.length();
Stack<int[]> stack = new Stack<>();
int[] temp = new int[3];
int max = 0;
for(int i = 0; i < l; i++){
char c = input.charAt(i);
if(c == '\n'){
//System.out.println("111");
int level = temp[0];
//将比当前级别高的都弹出去
while(!stack.isEmpty() && stack.peek()[0] >= level)
stack.pop();
//如果是文件夹
if(temp[2] == 0){
temp[1] = stack.isEmpty() ? temp[1] + 1 : stack.peek()[1] + temp[1] + 1;
stack.push(temp);
}else{
temp[1] = stack.isEmpty() ? temp[1] : stack.peek()[1] + temp[1];
max = Math.max(max, temp[1]);
}
//System.out.println(temp[1]);
temp = new int[3];
}else if(c == '\t'){
temp[0]++;
}else{
temp[1]++;
if(c == '.')
temp[2] = 1;
if(i == l - 1 && temp[2] == 1){
while(!stack.isEmpty() && temp[0] <= stack.peek()[0])
stack.pop();
temp[1] = stack.isEmpty() ? temp[1] : stack.peek()[1] + temp[1];
max = Math.max(max, temp[1]);
}
}
}
return max;
}
}
用数组模拟栈
class Solution:
def lengthLongestPath(self, input: str) -> int:
res = 0
n = len(input)
lv = [0] * n
level = 0
flag = False
length = 0
maxlen = 0
for c in input:
if c == '\t':
level += 1
elif c == '\n':
if level > 0:
length += lv[level - 1] + 1
if flag:
maxlen = max(maxlen, length)
else:
lv[level] = length
length = 0
flag = False
level = 0
else:
length += 1
if c == '.':
flag = True
if flag:
if level > 0:
length += lv[level - 1] + 1
maxlen = max(maxlen, length)
return maxlen