LeetCode 385. 迷你语法分析器 / 479. 最大回文数乘积 / 819. 最常见的单词

385. 迷你语法分析器

2022.4.15 每日一题

题目描述

给定一个字符串 s 表示一个整数嵌套列表,实现一个解析它的语法分析器并返回解析的结果 NestedInteger 。

列表中的每个元素只可能是整数或整数嵌套列表

示例 1:

输入:s = “324”,
输出:324
解释:你应该返回一个 NestedInteger 对象,其中只包含整数值 324。

示例 2:

输入:s = “[123,[456,[789]]]”,
输出:[123,[456,[789]]]
解释:返回一个 NestedInteger 对象包含一个有两个元素的嵌套列表:
1 一个 integer 包含值 123
2 一个包含两个元素的嵌套列表:
  i. 一个 integer 包含值 456
  ii. 一个包含一个元素的嵌套列表
    a. 一个 integer 包含值 789

提示:

1 <= s.length <= 5 * 10^4
s 由数字、方括号 “[]”、负号 ‘-’ 、逗号 ','组成
用例保证 s 是可解析的 NestedInteger
输入中的所有值的范围是 [-106, 106]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/mini-parser
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

有点奇怪的一道题
首先这个字符串可以是一个数字,或者是一个列表
这两种处理方式还不同,所以如果刚开始是数字的话,需要特殊处理
然后就和那种常规的括号嵌套题一样了
需要认真理解所给定的这个数据结构,其实就是刚刚说的两种形式,一种可以直接存放一个数字,另一种就是存放多个数字,也就是题目所说的列表;而且存放列表的时候,不需要去创建一个list存放,而是直接加入add就行了,其实和list差不多
那么自然而然想到栈,开始做的时候,栈里面存放的是字符串,我想的是遇到左括号,创建新的NestedInteger 对象,遇到右括号弹出数字放到这个对象中,然后返回到原来的父对象,这样就可以完成这个处理了
但是遇到了两个问题,首先就是最初的父对象的创建,因为需要一个临时变量充当父对象,如果遇到左括号创建新的对象,那么外面必须本来就有一层对象,这样就会导致多创建一层,输出表现上就是外面多一层括号;也想了很多办法去处理,比如第一次遍历不创建新的对象,但是一直报错,不知道为什么
第二个问题就是遍历得到的顺序,因为是弹出来后放入的,所以顺序会反过来
代码如下:

/**
 * // This is the interface that allows for creating nested lists.
 * // You should not implement it, or speculate about its implementation
 * public interface NestedInteger {
 *     // Constructor initializes an empty nested list.
 *     public NestedInteger();
 *
 *     // Constructor initializes a single integer.
 *     public NestedInteger(int value);
 *
 *     // @return true if this NestedInteger holds a single integer, rather than a nested list.
 *     public boolean isInteger();
 *
 *     // @return the single integer that this NestedInteger holds, if it holds a single integer
 *     // Return null if this NestedInteger holds a nested list
 *     public Integer getInteger();
 *
 *     // Set this NestedInteger to hold a single integer.
 *     public void setInteger(int value);
 *
 *     // Set this NestedInteger to hold a nested list and adds a nested integer to it.
 *     public void add(NestedInteger ni);
 *
 *     // @return the nested list that this NestedInteger holds, if it holds a nested list
 *     // Return empty list if this NestedInteger holds a single integer
 *     public List<NestedInteger> getList();
 * }
 */
class Solution {
    public NestedInteger deserialize(String s) {
        //说实话,没太看懂到底该怎么表示这个结果
        //但是单纯看这个题的话,应该就是用栈
        NestedInteger res = new NestedInteger();
        if(s.charAt(0) != '['){
            res.setInteger(Integer.parseInt(s));
            return res;
        }
        //用于记录上一层的列表
        Map<NestedInteger, NestedInteger> map = new HashMap<>();
        //map.put(res, new NestedInteger(Integer.MAX_VALUE));
        Stack<String> stack = new Stack();
        int l = s.length();
        for(int i = l - 1; i >= 0; i--){
            char c = s.charAt(i);
            if(c == ',')
                continue;
            else if(c == ']'){
                stack.push("]");
                NestedInteger temp = new NestedInteger();
                map.put(temp, res);
                res.add(temp);
                res = temp;
            }else if(c == '['){
                List<NestedInteger> list = new ArrayList<>();
                while(!stack.isEmpty() && !stack.peek().equals("]")){
                    String p = stack.pop();
                    int t = Integer.parseInt(p);
                    NestedInteger tt = new NestedInteger(t);
                    res.add(tt);
                }
                //for(int j = list.size() - 1; j >= 0; j--)
                //    res.add(list.get(j));
                stack.pop();
                res = map.get(res);
            //如果是数字
            }else{
                int flag = 1;
                if(c == '-')
                    flag = -1;
                int end = i - 1;
                //System.out.println(i);
                c = s.charAt(end);
                while(end >= 0 && (Character.isDigit(c) || c == '-')){
                    end--;
                    c = s.charAt(end);
                }
                String ss = s.substring(end + 1, i + 1);
                stack.push(ss);
                i = end + 1;
                //System.out.println(ss);
            }
        }

        while(map.containsKey(res)){
            //NestedInteger temp = map.get(res);
            //System.out.println(map.get(temp).getInteger());
            //if(map.get(temp).isInteger() && map.get(temp).getInteger() != Integer.MAX_VALUE)
            res = map.get(res);
        }
        return res;
    }
}

然后看了下题解是怎么写的,发现题解直接将这个对象存入了stack中,如果遇到数字就直接放在最近的对象中,遇到左括号创建新对象,遇到右括号弹出,我怎么就没想到呢。。。
主要关键点还是栈里存放的是这种对象

/**
 * // This is the interface that allows for creating nested lists.
 * // You should not implement it, or speculate about its implementation
 * public interface NestedInteger {
 *     // Constructor initializes an empty nested list.
 *     public NestedInteger();
 *
 *     // Constructor initializes a single integer.
 *     public NestedInteger(int value);
 *
 *     // @return true if this NestedInteger holds a single integer, rather than a nested list.
 *     public boolean isInteger();
 *
 *     // @return the single integer that this NestedInteger holds, if it holds a single integer
 *     // Return null if this NestedInteger holds a nested list
 *     public Integer getInteger();
 *
 *     // Set this NestedInteger to hold a single integer.
 *     public void setInteger(int value);
 *
 *     // Set this NestedInteger to hold a nested list and adds a nested integer to it.
 *     public void add(NestedInteger ni);
 *
 *     // @return the nested list that this NestedInteger holds, if it holds a nested list
 *     // Return empty list if this NestedInteger holds a single integer
 *     public List<NestedInteger> getList();
 * }
 */
class Solution {
    public NestedInteger deserialize(String s) {
        //说实话,没太看懂到底该怎么表示这个结果
        //但是单纯看这个题的话,应该就是用栈
        NestedInteger res = new NestedInteger();
        if(s.charAt(0) != '['){
            res.setInteger(Integer.parseInt(s));
            return res;
        }

        Stack<NestedInteger> stack = new Stack();
        int l = s.length();
        int num = 0;
        int flag = 1;
        for(int i = 0; i < l; i++){
            char c = s.charAt(i);
            //如果遇到逗号或者右括号,先放入数字
            if(c == ',' || c == ']'){
                //如果上一位是数字的话,放入该数字
                if(Character.isDigit(s.charAt(i - 1))){
                    NestedInteger top = stack.peek();
                    top.add(new NestedInteger(flag * num));
                }
                num = 0;
                flag = 1;
                //如果是右括号,说明上一层处理完了,放入上一层
                if(c == ']' && stack.size() > 1){
                    NestedInteger top = stack.pop();
                    stack.peek().add(top);
                }
            //如果是左括号,创建新的对象
            }else if(c == '['){
                NestedInteger t = new NestedInteger();
                stack.push(t);
            }else if(c == '-'){
                flag = -1;
            }else{
                num = num * 10 + c - '0';
            }
        }
        return stack.pop();
    }
}
class Solution:
    def deserialize(self, s: str) -> NestedInteger:
        if s[0] != '[':
            return NestedInteger(int(s))
        stack, num, negative = [], 0, False
        for i, c in enumerate(s):
            if c == '-':
                negative = True
            elif c.isdigit():
                num = num * 10 + int(c)
            elif c == '[':
                stack.append(NestedInteger())
            elif c in ',]':
                if s[i-1].isdigit():
                    if negative:
                        num = -num
                    stack[-1].add(NestedInteger(num))
                num, negative = 0, False
                if c == ']' and len(stack) > 1:
                    stack[-2].add(stack.pop())
        return stack.pop()

479. 最大回文数乘积

2022.4.16 每日一题

题目描述

给定一个整数 n ,返回 可表示为两个 n 位整数乘积的 最大回文整数 。因为答案可能非常大,所以返回它对 1337 取余 。

示例 1:

输入:n = 2
输出:987
解释:99 x 91 = 9009, 9009 % 1337 = 987

示例 2:

输入: n = 1
输出: 9

提示:

1 <= n <= 8

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-palindrome-product
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

题解给的竟然是暴力。
建议参考烟花大佬的题解:https://leetcode-cn.com/problems/largest-palindrome-product/solution/mei-ju-shu-xue-by-megurine-p1bn/
在一定程度上,用数学公式给了更简介有依据的方法

class Solution {
    public int largestPalindrome(int n) {
        //想想这样的整数有什么特点吗
        //首先范围是 10^(n - 1) * 10^(n -1) ~ (10^n) - 1 * 10^n - 1
        //又是一个数学问题
        //肯定不能一一列举,想想怎么弄
        //在这个范围内,从大到小,例如最大是99*99=9801,那么如果9打头还要想是回文,必须是末尾也是9
        //只有1*9,3*3是9,所以考虑91*99,93*93
        //同样,对于8开头,末尾是8,就考虑2*4,1*8

        //考虑的复杂了,竟然真的是枚举....
        
        if(n == 1)
            return 9;
        int res = 0;
        int left = (int)(Math.pow(10, n) - 1);
        for(int i = left; res == 0; i--){
            //先构造右半部分
            long num = i;
            int j = i;
            while(j > 0){
                num = num * 10 + j % 10;
                j /= 10;
            }
            //构造完以后判断能不能被整除
            long x = left;
            while(x * x >= num){
                if(num % x == 0){
                    res = (int)(num % 1337);
                    return res;
                }
                x--;
            }
        }
        return 0;
    }
}

range第一第二个参数限定的是范围

class Solution:
    def largestPalindrome(self, n: int) -> int:
        if n == 1:
            return 9
        max = 10 ** n - 1
        for i in range(max, max // 10, -1):
            num = i
            j = i
            while j:
                num = num * 10 + j % 10
                j //= 10
            x = max
            while x * x >= num:
                if num % x == 0:
                    return num % 1337
                x -= 1

819. 最常见的单词

2022.4.17 每日一题

题目描述

给定一个段落 (paragraph) 和一个禁用单词列表 (banned)。返回出现次数最多,同时不在禁用列表中的单词。

题目保证至少有一个词不在禁用列表中,而且答案唯一。

禁用列表中的单词用小写字母表示,不含标点符号。段落中的单词不区分大小写。答案都是小写字母。

示例:

输入:
paragraph = “Bob hit a ball, the hit BALL flew far after it was hit.”
banned = [“hit”]
输出: “ball”
解释:
“hit” 出现了3次,但它是一个禁用的单词。
“ball” 出现了2次 (同时没有其他单词出现2次),所以它是段落里出现次数最多的,且不在禁用列表中的单词。
注意,所有这些单词在段落里不区分大小写,标点符号需要忽略(即使是紧挨着单词也忽略, 比如 “ball,”),
"hit"不是最终的答案,虽然它出现次数更多,但它在禁用单词列表中。

提示:

1 <= 段落长度 <= 1000
0 <= 禁用单词个数 <= 100
1 <= 禁用单词长度 <= 10
答案是唯一的, 且都是小写字母 (即使在 paragraph 里是大写的,即使是一些特定的名词,答案都是小写的。)
paragraph 只包含字母、空格和下列标点符号!?’,;.
不存在没有连字符或者带有连字符的单词。
单词里只包含字母,不会出现省略号或者其他标点符号。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/most-common-word
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

模拟,不过细节不少

class Solution {
    public String mostCommonWord(String paragraph, String[] banned) {
        Map<String, Integer> map = new HashMap<>();
        Set<String> set = new HashSet<>();
        for(String s : banned)
            set.add(s);
        int l = paragraph.length();
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < l; i++){
            char c = paragraph.charAt(i);
            if(!Character.isLetter(c)){
                if(sb.length() == 0)
                    continue;
                String temp = sb.toString();
                sb = new StringBuffer();
                //System.out.println(temp);
                if(set.contains(temp))
                    continue;
                //System.out.println(temp);
                map.put(temp, map.getOrDefault(temp, 0) + 1);
                
                continue;
            }
            if(Character.isUpperCase(c)){
                c = (char)(c + 32);
                //System.out.println(c);
            }
            sb.append(c);
            if(i == l - 1){
                String temp = sb.toString();
                if(set.contains(temp))
                    continue;
                map.put(temp, map.getOrDefault(temp, 0) + 1);
            }
        }
        int max = 0;
        String res = "";
        for(String s : map.keySet()){
            if(map.get(s) > max){
                max = map.get(s);
                res = s;
            }
        }
        return res;
    }
}

哈希表对应这里的Counter
统计哈希表中最大数量的单词 max(counter.values())
一行的那种python代码就先不看了

class Solution:
    def mostCommonWord(self, paragraph: str, banned: List[str]) -> str:
        ban = set(banned)
        count = Counter()
        word, n = "", len(paragraph)
        for i in range(n + 1):
            if i < n and paragraph[i].isalpha():
                word += paragraph[i].lower()
            elif word:
                if word not in ban:
                    count[word] += 1
                word = ""
        maxc = max(count.values())
        for w in count:
            if count[w] == maxc:
                return w
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值