日渐头秃的代码日记--第311场周赛

135 阅读5分钟

这可能是最简单的一场周赛了,但是却有着灾难级的表现。。。

一、最小偶倍数

给你一个正整数 n ,返回 2n 的最小公倍数(正整数)。

 

示例 1:

输入: n = 5
输出: 10
解释: 5 和 2 的最小公倍数是 10 。

示例 2:

输入: n = 6
输出: 6
解释: 6 和 2 的最小公倍数是 6 。注意数字会是它自身的倍数。

 

提示:

  • 1 <= n <= 150

解析

因为其中一个数就是2,就看n是奇数还是偶数就行了 当然,如果另一个数不是2,可以用乘积除以最大公约数的方法

class Solution:
    def smallestEvenMultiple(self, n: int) -> int:
        if n % 2 == 0:
            return n
        else:
            return n * 2

二、最长的字母序连续子字符串的长度

字母序连续字符串 是由字母表中连续字母组成的字符串。换句话说,字符串 "abcdefghijklmnopqrstuvwxyz" 的任意子字符串都是 字母序连续字符串 。

  • 例如,"abc" 是一个字母序连续字符串,而 "acb" 和 "za" 不是。

给你一个仅由小写英文字母组成的字符串 s ,返回其 最长 的 字母序连续子字符串 的长度。

 

示例 1:

输入: s = "abacaba"
输出: 2
解释: 共有 4 个不同的字母序连续子字符串 "a""b""c""ab""ab" 是最长的字母序连续子字符串。

示例 2:

输入: s = "abcde"
输出: 5
解释: "abcde" 是最长的字母序连续子字符串。

 

提示:

  • 1 <= s.length <= 10^5
  • s 由小写英文字母组成

解析

从第二题开始就是灾难级的表现。。。

从字符串s第二个字符逐个遍历,看看当前字符是不是上一个字符的后一个字母就可以了。

class Solution:
    def longestContinuousSubstring(self, s: str) -> int:
        m = 1
        if len(s) == 1:
            return 1
        res = max(m, 1)
        for index, x in enumerate(s[1:]):
            if ord(x) == ord(s[index]) + 1:
                m += 1
                print(m)
            else:
                res = max(m, res)
                m = 1
        res = max(m, res)
        print(res)  # 灾难级表现在这里,因为写了print,第一次提交的时候没写return,导致多了一次错误提交
        return res

三、反转二叉树的奇数层

给你一棵 完美 二叉树的根节点 root ,请你反转这棵树中每个 奇数 层的节点值。

  • 例如,假设第 3 层的节点值是 [2,1,3,4,7,11,29,18] ,那么反转后它应该变成 [18,29,11,7,4,3,1,2] 。

反转后,返回树的根节点。

完美 二叉树需满足:二叉树的所有父节点都有两个子节点,且所有叶子节点都在同一层。

节点的 层数 等于该节点到根节点之间的边数。

 

示例 1:

输入: root = [2,3,5,8,13,21,34]
输出: [2,5,3,8,13,21,34]
解释:
这棵树只有一个奇数层。
在第 1 层的节点分别是 3、5 ,反转后为 5、3 。

示例 2:

输入: root = [7,13,11]
输出: [7,11,13]
解释: 
在第 1 层的节点分别是 13、11 ,反转后为 11、13 。 

示例 3:

输入: root = [0,1,2,0,0,0,0,1,1,1,1,2,2,2,2]
输出: [0,2,1,0,0,0,0,2,2,2,2,1,1,1,1]
解释: 奇数层由非零值组成。
在第 1 层的节点分别是 1、2 ,反转后为 2、1 。
在第 3 层的节点分别是 1、1、1、1、2、2、2、2 ,反转后为 2、2、2、2、1、1、1、1 。

 

提示:

  • 树中的节点数目在范围 [1, 2^14] 内
  • 0 <= Node.val <= 10^5
  • root 是一棵 完美 二叉树

解析

这个输入是一个根节点,要是一个数组,就直接用数学的方法重写一下几个index位置的数值就可以。

回到本题,使用二叉树的层序遍历即可,因为是完美二叉树,难度也降低了一些。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def reverseOddLevels(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        stack = [root]
        lay_num = 1
        while stack:
            lay = []
            lay_value = []
            for node in stack:
                lay_value.append(node.val)
                if node.left:
                    lay.append(node.left)
                if node.right:
                    lay.append(node.right)
            
            lay_num += 1
            if lay_num % 2 == 1:
                lay_value = lay_value[::-1]
                print(lay_value)
                for index, node in enumerate(stack):
                    node.val = lay_value[index]  # 灾难表现在这里,定义的TreeNode的值用的是val,而不是value,周赛的时候这里写成了node.value = lay_value[index],调试了四十多分钟,结果一直不对,一直跟原有的树一模一样。。。
            stack = lay  # 将当前层的节点保留下来,便于下一次遍历
        return root

四、字符串的前缀分数和

给你一个长度为 n 的数组 words ,该数组由 非空 字符串组成。

定义字符串 word 的 分数 等于以 word 作为 前缀 的 words[i] 的数目。

  • 例如,如果 words = ["a", "ab", "abc", "cab"] ,那么 "ab" 的分数是 2 ,因为 "ab" 是 "ab" 和 "abc" 的一个前缀。

返回一个长度为 **n 的数组 **answer **,其中 **answer[i] **是 **words[i] 的每个非空前缀的分数 总和 

注意: 字符串视作它自身的一个前缀。

 

示例 1:

输入: words = ["abc","ab","bc","b"]
输出: [5,4,3,2]
解释: 对应每个字符串的答案如下:
- "abc"3 个前缀:"a""ab""abc" 。
- 2 个字符串的前缀为 "a"2 个字符串的前缀为 "ab"1 个字符串的前缀为 "abc" 。
总计 answer[0] = 2 + 2 + 1 = 5 。
- "ab"2 个前缀:"a""ab" 。
- 2 个字符串的前缀为 "a"2 个字符串的前缀为 "ab" 。
总计 answer[1] = 2 + 2 = 4 。
- "bc"2 个前缀:"b""bc" 。
- 2 个字符串的前缀为 "b"1 个字符串的前缀为 "bc" 。 
总计 answer[2] = 2 + 1 = 3 。
- "b"1 个前缀:"b"。
- 2 个字符串的前缀为 "b" 。
总计 answer[3] = 2

示例 2:

输入: words = ["abcd"]
输出: [4]
解释:
"abcd" 有 4 个前缀 "a"、"ab"、"abc" 和 "abcd"。
每个前缀的分数都是 1 ,总计 answer[0] = 1 + 1 + 1 + 1 = 4

 

提示:

  • 1 <= words.length <= 1000
  • 1 <= words[i].length <= 1000
  • words[i] 由小写英文字母组成

解析

能看懂题目要求,但是是一个未接触过的数据结构,叫做前缀树,于是参考了一下208. 实现 Trie (前缀树) - 力扣(LeetCode) 这道题的解析,构造了基础的前缀树,同时因为需要计数,出现了多少次,于是给每个字母节点增加一个计数字段。

class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.cnt = 0
    
    def startsWith(self, prefix: str) -> int:
        node = self
        res = 0
        for ch in prefix:
            ch = ord(ch) - ord("a")
            if not node.children[ch]:  # 当找到第一个没有出现的字母,立即停止,第一次提交代码的时候,这里直接跳过了,改成了  if node.children[ch],就会导致计数错误
                return res
            node = node.children[ch]
            res += node.cnt
        return res

    def insert(self, word: str) -> None:
        node = self
        for ch in word:
            ch = ord(ch) - ord("a")
            if not node.children[ch]:
                node.children[ch] = Trie()
            node = node.children[ch]
            node.cnt += 1
            # print("insert %s %s %s" % (word, ch, node.cnt))  # print的内容过多,也会导致提交失败,超出长度限制了


class Solution:
    def sumPrefixScores(self, words: List[str]) -> List[int]:
        trie = Trie()
        for word in words:
            trie.insert(word)
        res = []
        for word in words:
            res.append(trie.startsWith(word))
        # print(res)
        return res