LeetCode 386. 字典序排数 / 821. 字符的最短距离 / 388. 文件的最长绝对路径

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
            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值