zoukankan      html  css  js  c++  java
  • 【leetcode】周赛记录

    目录:

    1. 2020年9月13日 -- 周赛
    2. 2020年10月31日 -- 双周赛
    3. 2020年11月1日 -- 周赛
    4. 2020年11月8日 -- 周赛
    5. 2020年11月28日 -- 双周赛

    2020年9月13日 -- 周赛

    做对了两道题。

    1582. 二进制矩阵中的特殊位置 -- 简单

    题目链接:https://leetcode-cn.com/problems/special-positions-in-a-binary-matrix/

    题目描述

    给你一个大小为 rows x cols 的矩阵 mat,其中 mat[i][j] 是 0 或 1,请返回 矩阵 mat 中特殊位置的数目。
    特殊位置 定义:如果 mat[i][j] == 1 并且第 i 行和第 j 列中的所有其他元素均为 0(行和列的下标均 从 0 开始 ),则位置 (i, j) 被称为特殊位置。

    示例 1:
    输入:mat =
    [[1,0,0],
    [0,0,1],
    [1,0,0]]
    输出:1
    解释:(1,2) 是一个特殊位置,因为 mat[1][2] == 1 且所处的行和列上所有其他元素都是 0

    示例 2:
    输入:mat =
    [[1,0,0],
    [0,1,0],
    [0,0,1]]
    输出:3
    解释:(0,0), (1,1) 和 (2,2) 都是特殊位置

    示例 3:
    输入:mat =
    [[0,0,0,1],
    [1,0,0,0],
    [0,1,1,0],
    [0,0,0,0]]
    输出:2

    示例 4:
    输入:mat =
    [[0,0,0,0,0],
    [1,0,0,0,0],
    [0,1,0,0,0],
    [0,0,1,0,0],
    [0,0,0,1,1]]
    输出:3
     
    提示:
    rows == mat.length
    cols == mat[i].length
    1 <= rows, cols <= 100
    mat[i][j] 是 0 或 1

    解题思路

    统计每行每列之和,如果为1,则根据行列定位所求的特殊位置。

    代码

    class Solution:
        def numSpecial(self, mat: List[List[int]]) -> int:
            if mat is None or len(mat) == 0 or len(mat[0]) == 0:
                return 0
            
            rows = len(mat)
            cols = len(mat[0])
            
            rows_sum = [0]*rows
            cols_sum = [0]*cols
            
            for i in range(rows):
                for j in range(cols):
                    rows_sum[i] += mat[i][j]
                    cols_sum[j] += mat[i][j]
                    
            rst = 0
            
            for i in range(rows):
                for j in range(cols):
                    if rows_sum[i] == 1 and cols_sum[j] == 1 and mat[i][j] == 1:
                        rst += 1
                        
            return rst
    

    1583. 统计不开心的朋友 -- 中等

    题目链接:https://leetcode-cn.com/problems/count-unhappy-friends/

    题目描述

    给你一份 n 位朋友的亲近程度列表,其中 n 总是 偶数 。

    对每位朋友 i,preferences[i] 包含一份 按亲近程度从高到低排列 的朋友列表。换句话说,排在列表前面的朋友与 i 的亲近程度比排在列表后面的朋友更高。每个列表中的朋友均以 0 到 n-1 之间的整数表示。

    所有的朋友被分成几对,配对情况以列表 pairs 给出,其中 pairs[i] = [xi, yi] 表示 xi 与 yi 配对,且 yi 与 xi 配对。

    但是,这样的配对情况可能会是其中部分朋友感到不开心。在 x 与 y 配对且 u 与 v 配对的情况下,如果同时满足下述两个条件,x 就会不开心:
    x 与 u 的亲近程度胜过 x 与 y,且
    u 与 x 的亲近程度胜过 u 与 v
    返回 不开心的朋友的数目 。

    示例 1:
    输入:n = 4, preferences = [[1, 2, 3], [3, 2, 0], [3, 1, 0], [1, 2, 0]], pairs = [[0, 1], [2, 3]]
    输出:2
    解释:
    朋友 1 不开心,因为:

    • 1 与 0 配对,但 1 与 3 的亲近程度比 1 与 0 高,且
    • 3 与 1 的亲近程度比 3 与 2 高。
      朋友 3 不开心,因为:
    • 3 与 2 配对,但 3 与 1 的亲近程度比 3 与 2 高,且
    • 1 与 3 的亲近程度比 1 与 0 高。
      朋友 0 和 2 都是开心的。

    示例 2:
    输入:n = 2, preferences = [[1], [0]], pairs = [[1, 0]]
    输出:0
    解释:朋友 0 和 1 都开心。

    示例 3:
    输入:n = 4, preferences = [[1, 3, 2], [2, 3, 0], [1, 3, 0], [0, 2, 1]], pairs = [[1, 3], [0, 2]]
    输出:4

    提示:
    2 <= n <= 500
    n 是偶数
    preferences.length == n
    preferences[i].length == n - 1
    0 <= preferences[i][j] <= n - 1
    preferences[i] 不包含 i
    preferences[i] 中的所有值都是独一无二的
    pairs.length == n/2
    pairs[i].length == 2
    xi != yi
    0 <= xi, yi <= n - 1
    每位朋友都 恰好 被包含在一对中

    解题思路

    给排序赋值,然后遍历既可,找出不开心的对。
    注意下这里的二位数组的初始化,要逐行初始化。不能直接[[0]n]n。

    代码

    class Solution:
        def unhappyFriends(self, n: int, preferences: List[List[int]], pairs: List[List[int]]) -> int:
            prefer_weight = [] # 值越小表示关系越近
            for i in range(n):
                temp = [0]*n
                prefer_weight.append(temp)
            
            for i in range(n):
                for j in range(n-1):
                    a = i
                    b = preferences[i][j]
                    #print(b)
                    prefer_weight[a][b] = j+1
                #print(prefer_weight)
                
            #print(prefer_weight)
                    
            link = [-1]*n
            
            for i in range(len(pairs)):
                a, b = pairs[i][0], pairs[i][1]
                link[a] = b
                link[b] = a
                
            #print(link)
                
            more_prefer = []
            for i in range(n):
                temp = [0]*n
                more_prefer.append(temp)
            
            for i in range(n):
                for j in range(n):
                    now_weight = prefer_weight[i][j]
                    link_weight = prefer_weight[i][link[i]]
                    #print(now_weight, link_weight)
                    if now_weight != 0 and now_weight < link_weight:
                        more_prefer[i][j] = 1
            
            #print(more_prefer)
            
            unhappy = [0]*n
            
            for i in range(n):
                for j in range(n):
                    if more_prefer[i][j] == 1 and more_prefer[j][i] == 1:
                        unhappy[i] = 1
                        unhappy[j] = 1
            
            return sum(unhappy)
    

    返回目录

    2020年10月31日 -- 双周赛

    做对了前三道,第四道运行超时了。赛后参考了一下其他人的代码,重新做了提交。

    1. 按照频率将数组升序排序 -- 简单

    题目链接:https://leetcode-cn.com/problems/sort-array-by-increasing-frequency/

    题目描述:

    给你一个整数数组 nums ,请你将数组按照每个值的频率 升序 排序。如果有多个值的频率相同,请你按照数值本身将它们 降序 排序。 
    请你返回排序后的数组。

    示例 1:
    输入:nums = [1,1,2,2,2,3]
    输出:[3,1,1,2,2,2]
    解释:'3' 频率为 1,'1' 频率为 2,'2' 频率为 3 。

    示例 2:
    输入:nums = [2,3,1,3,2]
    输出:[1,3,3,2,2]
    解释:'2' 和 '3' 频率都为 2 ,所以它们之间按照数值本身降序排序。

    示例 3:
    输入:nums = [-1,1,-6,4,5,-6,1,4,1]
    输出:[5,-1,4,4,-6,-6,1,1,1]
     
    提示:
    1 <= nums.length <= 100
    -100 <= nums[i] <= 100

    思路解析:

    用python实现非常简单。即使不用sorted,自己写个排序也不难。

    代码:

    class Solution:
        def frequencySort(self, nums: List[int]) -> List[int]:
            dic = {}
            for num in nums:
                if num not in dic:
                    dic[num] = 0
                dic[num] += 1
            temp_lst = sorted(dic.items(), key = lambda d: (d[1], -d[0]), reverse=False)
            rst_lst = []
            for temp in temp_lst:
                for i in range(temp[1]):
                    rst_lst.append(temp[0])
            return rst_lst
    

    2. 两点之间不包含任何点的最宽垂直面积 -- 中等

    题目链接:https://leetcode-cn.com/problems/widest-vertical-area-between-two-points-containing-no-points/

    题目描述:

    给你 n 个二维平面上的点 points ,其中 points[i] = [xi, yi] ,请你返回两点之间内部不包含任何点的 最宽垂直面积 的宽度。
    垂直面积 的定义是固定宽度,而 y 轴上无限延伸的一块区域(也就是高度为无穷大)。 最宽垂直面积 为宽度最大的一个垂直面积。
    请注意,垂直区域 边上 的点 不在 区域内。

    示例 1:
    输入:points = [[8,7],[9,9],[7,4],[9,7]]
    输出:1

    示例 2:
    输入:points = [[3,1],[9,0],[1,0],[1,4],[5,3],[8,8]]
    输出:3

    提示:
    n == points.length
    2 <= n <= 105
    points[i].length == 2
    0 <= xi, yi <= 109

    思路解析:

    算一下横坐标的最大间隔就可以了。

    代码:

    class Solution:
        def maxWidthOfVerticalArea(self, points: List[List[int]]) -> int:
            dic = {}
            for pairs in points:
                if pairs[0] not in dic:
                    dic[pairs[0]] = 1
            lst = sorted([i for i in dic.keys()])
            max_len = 0
            for i in range(1, len(lst)):
                temp = lst[i] - lst[i-1]
                if temp > max_len:
                    max_len = temp
            return max_len
    

    3. 统计只差一个字符的子串数目 -- 中等

    题目链接:https://leetcode-cn.com/problems/count-substrings-that-differ-by-one-character/

    题目描述:

    给你两个字符串 s 和 t ,请你找出 s 中的非空子串的数目,这些子串满足替换 一个不同字符 以后,是 t 串的子串。换言之,请你找到 s 和 t 串中 恰好 只有一个字符不同的子字符串对的数目。
    比方说, "computer" 和 "computation" 加粗部分只有一个字符不同: 'e'/'a' ,所以这一对子字符串会给答案加 1 。
    请你返回满足上述条件的不同子字符串对数目。
    一个 子字符串 是一个字符串中连续的字符。

    示例 1:
    输入:s = "aba", t = "baba"
    输出:6
    解释:以下为只相差 1 个字符的 s 和 t 串的子字符串对:
    ("aba", "baba")
    ("aba", "baba")
    ("aba", "baba")
    ("aba", "baba")
    ("aba", "baba")
    ("aba", "baba")
    加粗部分分别表示 s 和 t 串选出来的子字符串。

    示例 2:
    输入:s = "ab", t = "bb"
    输出:3
    解释:以下为只相差 1 个字符的 s 和 t 串的子字符串对:
    ("ab", "bb")
    ("ab", "bb")
    ("ab", "bb")
    加粗部分分别表示 s 和 t 串选出来的子字符串。

    示例 3:
    输入:s = "a", t = "a"
    输出:0

    示例 4:
    输入:s = "abe", t = "bbc"
    输出:10

    提示:
    1 <= s.length, t.length <= 100
    s 和 t 都只包含小写英文字母。

    解题思路:

    暴力解法,遍历一下就可以了。

    代码:

    class Solution:
        def countSubstrings(self, s: str, t: str) -> int:
            max_len = min(len(s), len(t))
            cnt = 0
            for s_len in range(1, max_len+1):
                for i in range(len(s)-s_len+1):
                    s_temp = s[i:i+s_len]
                    for j in range(len(t)-s_len+1):
                        t_temp = t[j:j+s_len]
                        if self.only_one_diff(s_temp, t_temp):
                            #print(s_temp, i, t_temp, j)
                            cnt += 1
            return cnt
        
        def only_one_diff(self, s, t):
            if len(s) != len(t):
                return False
            cnt = 0
            for i in range(len(s)):
                if s[i] != t[i]:
                    cnt += 1
            if cnt == 1:
                return True
            return False
    

    4. 通过给定词典构造目标字符串的方案数 -- 困难

    题目链接:https://leetcode-cn.com/problems/number-of-ways-to-form-a-target-string-given-a-dictionary/

    题目描述:

    给你一个字符串列表 words 和一个目标字符串 target 。words 中所有字符串都 长度相同  。
    你的目标是使用给定的 words 字符串列表按照下述规则构造 target :

    • 从左到右依次构造 target 的每一个字符。
    • 为了得到 target 第 i 个字符(下标从 0 开始),当 target[i] = words[j][k] 时,你可以使用 words 列表中第 j 个字符串的第 k 个字符。
    • 一旦你使用了 words 中第 j 个字符串的第 k 个字符,你不能再使用 words 字符串列表中任意单词的第 x 个字符(x <= k)。也就是说,所有单词下标小于等于 k 的字符都不能再被使用。
    • 请你重复此过程直到得到目标字符串 target 。

    请注意, 在构造目标字符串的过程中,你可以按照上述规定使用 words 列表中 同一个字符串 的 多个字符 。
    请你返回使用 words 构造 target 的方案数。由于答案可能会很大,请对 109 + 7 取余 后返回。

    (译者注:此题目求的是有多少个不同的 k 序列,详情请见示例。)

    示例 1:
    输入:words = ["acca","bbbb","caca"], target = "aba"
    输出:6
    解释:总共有 6 种方法构造目标串。
    "aba" -> 下标为 0 ("acca"),下标为 1 ("bbbb"),下标为 3 ("caca")
    "aba" -> 下标为 0 ("acca"),下标为 2 ("bbbb"),下标为 3 ("caca")
    "aba" -> 下标为 0 ("acca"),下标为 1 ("bbbb"),下标为 3 ("acca")
    "aba" -> 下标为 0 ("acca"),下标为 2 ("bbbb"),下标为 3 ("acca")
    "aba" -> 下标为 1 ("caca"),下标为 2 ("bbbb"),下标为 3 ("acca")
    "aba" -> 下标为 1 ("caca"),下标为 2 ("bbbb"),下标为 3 ("caca")

    示例 2:
    输入:words = ["abba","baab"], target = "bab"
    输出:4
    解释:总共有 4 种不同形成 target 的方法。
    "bab" -> 下标为 0 ("baab"),下标为 1 ("baab"),下标为 2 ("abba")
    "bab" -> 下标为 0 ("baab"),下标为 1 ("baab"),下标为 3 ("baab")
    "bab" -> 下标为 0 ("baab"),下标为 2 ("baab"),下标为 3 ("baab")
    "bab" -> 下标为 1 ("abba"),下标为 2 ("baab"),下标为 3 ("baab")

    示例 3:
    输入:words = ["abcd"], target = "abcd"
    输出:1

    示例 4:
    输入:words = ["abab","baba","abba","baab"], target = "abba"
    输出:16

    提示:
    1 <= words.length <= 1000
    1 <= words[i].length <= 1000
    words 中所有单词长度相同。
    1 <= target.length <= 1000
    words[i] 和 target 都仅包含小写英文字母。

    解题思路

    做位运算,或者递归,容易超时。
    这里用表实现迭代,可以满足题目要求。

    代码

    class Solution:
        def numWays(self, words: List[str], target: str) -> int:
            word_len = len(words[0])
            target_len = len(target)
            
            cnt = [[0] * 26 for _ in range(word_len)] # 存放words的每一个字符的频次
            
            for word in words:
                for i, char in enumerate(word):
                    cnt[i][ord(char)-ord('a')] += 1 # 统计频次
            
            dp = [[0]*(target_len+1) for _ in range(word_len+1)] # dp大小是(word_len+1)*(target_len)*1
            
            for i in range(word_len+1): 
                dp[i][0] = 1 # 该列全部置为1,是为了保证在后面乘法计算时,从1开始乘
                
            for i in range(word_len):
                for j in range(target_len):
                    # i, j   -> i+1, j+1   匹配下一个word字母,及下一个target字母
                    # cnt[i][ord(target[j])-ord('a')] 为0与否,说明匹配是否成功,匹配成功则乘上所有word里都有该字母的数量
                    # i, j+1 -> i+1, j+1   直接跳过,匹配下一个word字母
                    dp[i+1][j+1] = dp[i][j] * cnt[i][ord(target[j])-ord('a')] + dp[i][j+1]
                    
            return dp[word_len][target_len] % 1000000007
    

    返回目录

    2020年11月1日 -- 周赛

    做对了前两道,第三道超时了。第三道题目测试数据太弱了,居然直接先堆砖再用梯子就可以AC。

    1. 能否连接形成数组 -- 简单

    题目链接:https://leetcode-cn.com/problems/check-array-formation-through-concatenation/

    题目描述:

    给你一个整数数组 arr ,数组中的每个整数 互不相同 。另有一个由整数数组构成的数组 pieces,其中的整数也 互不相同 。请你以 任意顺序 连接 pieces 中的数组以形成 arr 。但是,不允许 对每个数组 pieces[i] 中的整数重新排序。
    如果可以连接 pieces 中的数组形成 arr ,返回 true ;否则,返回 false 。

    示例 1:
    输入:arr = [85], pieces = [[85]]
    输出:true

    示例 2:
    输入:arr = [15,88], pieces = [[88],[15]]
    输出:true
    解释:依次连接 [15] 和 [88]

    示例 3:
    输入:arr = [49,18,16], pieces = [[16,18,49]]
    输出:false
    解释:即便数字相符,也不能重新排列 pieces[0]

    示例 4:
    输入:arr = [91,4,64,78], pieces = [[78],[4,64],[91]]
    输出:true
    解释:依次连接 [91]、[4,64] 和 [78]

    示例 5:
    输入:arr = [1,3,5,7], pieces = [[2,4,6,8]]
    输出:false

    提示:
    1 <= pieces.length <= arr.length <= 100
    sum(pieces[i].length) == arr.length
    1 <= pieces[i].length <= arr.length
    1 <= arr[i], pieces[i][j] <= 100
    arr 中的整数 互不相同
    pieces 中的整数 互不相同(也就是说,如果将 pieces 扁平化成一维数组,数组中的所有整数互不相同)

    解题思路:

    很简单,遍历一下就可以。

    代码:

    class Solution:
        def canFormArray(self, arr: List[int], pieces: List[List[int]]) -> bool:
            len_arr = len(arr)
            len_pieces = sum([len(piece) for piece in pieces])
            if len_arr != len_pieces:
                return False
            
            index = 0
            while index < len_arr:
                temp_index = index
                for i in range(len(pieces)):
                    piece = pieces[i]
                    if piece[0] == arr[index]:
                        for j in range(len(piece)):
                            if piece[j] == arr[index]:
                                index += 1
                            else:
                                return False
                        break
                if temp_index == index:
                    return False
            
            return True
    

    2. 统计字典序元音字符串的数目 -- 中等

    题目链接:https://leetcode-cn.com/problems/count-sorted-vowel-strings/

    题目描述:

    给你一个整数 n,请返回长度为 n 、仅由元音 (a, e, i, o, u) 组成且按 字典序排列 的字符串数量。
    字符串 s 按 字典序排列 需要满足:对于所有有效的 i,s[i] 在字母表中的位置总是与 s[i+1] 相同或在 s[i+1] 之前。

    示例 1:
    输入:n = 1
    输出:5
    解释:仅由元音组成的 5 个字典序字符串为 ["a","e","i","o","u"]

    示例 2:
    输入:n = 2
    输出:15
    解释:仅由元音组成的 15 个字典序字符串为
    ["aa","ae","ai","ao","au","ee","ei","eo","eu","ii","io","iu","oo","ou","uu"]
    注意,"ea" 不是符合题意的字符串,因为 'e' 在字母表中的位置比 'a' 靠后

    示例 3:
    输入:n = 33
    输出:66045

    提示:
    1 <= n <= 50

    解题思路:

    用数组去存储字符串会超时。正确的做法是直接推算一下,用矩阵存储结果。

    代码:

    class Solution:
        def countVowelStrings(self, n: int) -> int:
            matrix = []
            for i in range(5):
                matrix.append([0]*(n+1))
                
            for i in range(5):
                matrix[i][0] = 1
                
            for j in range(1, n+1):
                for i in range(5):
                    for t in range(i+1):
                        matrix[i][j] += matrix[t][j-1]
            
            return matrix[4][n]
    

    3. 可以到达的最远建筑 -- 中等

    题目链接:https://leetcode-cn.com/problems/furthest-building-you-can-reach/

    题目描述:

    给你一个整数数组 heights ,表示建筑物的高度。另有一些砖块 bricks 和梯子 ladders 。
    你从建筑物 0 开始旅程,不断向后面的建筑物移动,期间可能会用到砖块或梯子。
    当从建筑物 i 移动到建筑物 i+1(下标 从 0 开始 )时:
    如果当前建筑物的高度 大于或等于 下一建筑物的高度,则不需要梯子或砖块
    如果当前建筑的高度 小于 下一个建筑的高度,您可以使用 一架梯子 或 (h[i+1] - h[i]) 个砖块
    如果以最佳方式使用给定的梯子和砖块,返回你可以到达的最远建筑物的下标(下标 从 0 开始 )。

    示例 1:
    输入:heights = [4,2,7,6,9,14,12], bricks = 5, ladders = 1
    输出:4
    解释:从建筑物 0 出发,你可以按此方案完成旅程:

    • 不使用砖块或梯子到达建筑物 1 ,因为 4 >= 2
    • 使用 5 个砖块到达建筑物 2 。你必须使用砖块或梯子,因为 2 < 7
    • 不使用砖块或梯子到达建筑物 3 ,因为 7 >= 6
    • 使用唯一的梯子到达建筑物 4 。你必须使用砖块或梯子,因为 6 < 9
      无法越过建筑物 4 ,因为没有更多砖块或梯子。

    示例 2:
    输入:heights = [4,12,2,7,3,18,20,3,19], bricks = 10, ladders = 2
    输出:7

    示例 3:
    输入:heights = [14,3,19,3], bricks = 17, ladders = 0
    输出:3

    提示:
    1 <= heights.length <= 105
    1 <= heights[i] <= 106
    0 <= bricks <= 109
    0 <= ladders <= heights.length

    解题思路:

    因为梯子没有限制高度,所以应当尽可能把梯子放在楼层差更大的地方。
    所以要求楼层差的最大N位数,涉及到排序。
    以下代码思路应该对,不过会超时。(待优化)

    代码:

    class Solution:
        def furthestBuilding(self, heights: List[int], bricks: int, ladders: int) -> int:
            # 主要是充分利用梯子,在楼层差最大时使用
            diff = []
            for i in range(1, len(heights)):
                if heights[i] <= heights[i-1]:
                    diff.append(0)
                else:
                    diff.append(heights[i]-heights[i-1])
            
            """
            # 楼层差排序
            diff_dic = {}
            for i in range(len(diff)):
                if diff[i] != 0:
                    diff_dic[i] = diff[i]
            
            sort_lst = sorted(diff_dic.items(), key = lambda d: (-d[1], d[0]), reverse=False)
            """
            #print(diff)
            
            diff_sum = 0
            max_path = 0
            temp_lst = [0]
            for i in range(len(diff)):
                diff_sum += diff[i]
                for t in range(len(temp_lst)):
                    if temp_lst[t] <= diff[i]:
                        temp_lst.insert(t, diff[i])
                        break
                #temp_lst = sorted(diff[:i+1], reverse=True)
                replace_sum = sum(temp_lst[:ladders])
                #print(temp_lst)
                #print(diff_sum, bricks, replace_sum)
                if diff_sum <= bricks + replace_sum:
                    max_path = i+1
                else:
                    break
            return max_path
    

    返回目录

    2020年11月8日 -- 周赛

    做对了前三道,第四道超时了。

    1. 获取生成数组中的最大值

    题目链接:https://leetcode-cn.com/problems/get-maximum-in-generated-array/

    题目描述:

    给你一个整数 n 。按下述规则生成一个长度为 n + 1 的数组 nums :
    nums[0] = 0
    nums[1] = 1
    当 2 <= 2 * i <= n 时,nums[2 * i] = nums[i]
    当 2 <= 2 * i + 1 <= n 时,nums[2 * i + 1] = nums[i] + nums[i + 1]
    返回生成数组 nums 中的 最大 值。

    示例 1:
    输入:n = 7
    输出:3
    解释:根据规则:
    nums[0] = 0
    nums[1] = 1
    nums[(1 * 2) = 2] = nums[1] = 1
    nums[(1 * 2) + 1 = 3] = nums[1] + nums[2] = 1 + 1 = 2
    nums[(2 * 2) = 4] = nums[2] = 1
    nums[(2 * 2) + 1 = 5] = nums[2] + nums[3] = 1 + 2 = 3
    nums[(3 * 2) = 6] = nums[3] = 2
    nums[(3 * 2) + 1 = 7] = nums[3] + nums[4] = 2 + 1 = 3
    因此,nums = [0,1,1,2,1,3,2,3],最大值 3

    示例 2:
    输入:n = 2
    输出:1
    解释:根据规则,nums[0]、nums[1] 和 nums[2] 之中的最大值是 1

    示例 3:
    输入:n = 3
    输出:2
    解释:根据规则,nums[0]、nums[1]、nums[2] 和 nums[3] 之中的最大值是 2
     
    提示:
    0 <= n <= 100

    代码:

    class Solution:
        def getMaximumGenerated(self, n: int) -> int:
            nums = [0]*(n+1)
            max_num = 0
                
            if n > 0:
                nums[1] = 1
                max_num = 1
                    
            for i in range(2, n+1):
                if i % 2 == 0:
                    nums[i] = nums[i//2]
                    if nums[i] > max_num:
                        max_num = nums[i]
                else:
                    nums[i] = nums[i//2] + nums[i//2 + 1]
                    if nums[i] > max_num:
                        max_num = nums[i]
            return max_num
    

    返回目录

    2. 字符频次唯一的最小删除次数 -- 中等

    题目链接:https://leetcode-cn.com/problems/minimum-deletions-to-make-character-frequencies-unique/

    题目描述:

    如果字符串 s 中 不存在 两个不同字符 频次 相同的情况,就称 s 是 优质字符串 。
    给你一个字符串 s,返回使 s 成为 优质字符串 需要删除的 最小 字符数。
    字符串中字符的 频次 是该字符在字符串中的出现次数。例如,在字符串 "aab" 中,'a' 的频次是 2,而 'b' 的频次是 1 。

    示例 1:
    输入:s = "aab"
    输出:0
    解释:s 已经是优质字符串。

    示例 2:
    输入:s = "aaabbbcc"
    输出:2
    解释:可以删除两个 'b' , 得到优质字符串 "aaabcc" 。
    另一种方式是删除一个 'b' 和一个 'c' ,得到优质字符串 "aaabbc" 。

    示例 3:
    输入:s = "ceabaacb"
    输出:2
    解释:可以删除两个 'c' 得到优质字符串 "eabaab" 。
    注意,只需要关注结果字符串中仍然存在的字符。(即,频次为 0 的字符会忽略不计。)
     
    提示:
    1 <= s.length <= 105
    s 仅含小写英文字母

    代码:

    class Solution:
        def minDeletions(self, s: str) -> int:
            dic = {}
            for i in range(len(s)):
                if s[i] not in dic:
                    dic[s[i]] = 0
                dic[s[i]] += 1
            
            dic_num = {}
            for k, v in dic.items():
                if v not in dic_num:
                    dic_num[v] = 0
                dic_num[v] += 1
            
            cnt = 0
            
            dic_num_cp = {}
            for k, v in dic_num.items():
                dic_num_cp[k] = v
                
            for k, v in dic_num.items():
                k_cp = k
                v_cp = v
                while v_cp > 1:
                    k_cp -= 1
                    cnt += 1
                    if k_cp not in dic_num_cp or k_cp == 0:
                        dic_num_cp[k_cp] = 1
                        v_cp -= 1
                        k_cp = k # 重置
                    else:
                        continue
                    
            return cnt
    

    返回目录

    3. 销售价值减少的颜色球 -- 中等

    题目链接:https://leetcode-cn.com/problems/sell-diminishing-valued-colored-balls/

    题目描述:

    你有一些球的库存 inventory ,里面包含着不同颜色的球。一个顾客想要 任意颜色 总数为 orders 的球。
    这位顾客有一种特殊的方式衡量球的价值:每个球的价值是目前剩下的 同色球 的数目。比方说还剩下 6 个黄球,那么顾客买第一个黄球的时候该黄球的价值为 6 。这笔交易以后,只剩下 5 个黄球了,所以下一个黄球的价值为 5 (也就是球的价值随着顾客购买同色球是递减的)
    给你整数数组 inventory ,其中 inventory[i] 表示第 i 种颜色球一开始的数目。同时给你整数 orders ,表示顾客总共想买的球数目。你可以按照 任意顺序 卖球。
    请你返回卖了 orders 个球以后 最大 总价值之和。由于答案可能会很大,请你返回答案对 109 + 7 取余数 的结果。

    示例 1:
    输入:inventory = [2,5], orders = 4
    输出:14
    解释:卖 1 个第一种颜色的球(价值为 2 ),卖 3 个第二种颜色的球(价值为 5 + 4 + 3)。
    最大总和为 2 + 5 + 4 + 3 = 14 。

    示例 2:
    输入:inventory = [3,5], orders = 6
    输出:19
    解释:卖 2 个第一种颜色的球(价值为 3 + 2),卖 4 个第二种颜色的球(价值为 5 + 4 + 3 + 2)。
    最大总和为 3 + 2 + 5 + 4 + 3 + 2 = 19 。

    示例 3:
    输入:inventory = [2,8,4,10,6], orders = 20
    输出:110

    示例 4:
    输入:inventory = [1000000000], orders = 1000000000
    输出:21
    解释:卖 1000000000 次第一种颜色的球,总价值为 500000000500000000 。 500000000500000000 对 109 + 7 取余为 21 。

    提示:
    1 <= inventory.length <= 105
    1 <= inventory[i] <= 109
    1 <= orders <= min(sum(inventory[i]), 109)

    解题思路:

    先排序,然后再计算。

    代码:

    class Solution:
        def maxProfit(self, inventory: List[int], orders: int) -> int:
            values = 0
            
            lst = sorted(inventory, reverse=True)
            lst.append(0)
            
            #print(lst)
            
            diff = [0]*(len(lst)-1)
            for i in range(len(lst)-1):
                diff[i] = lst[i] - lst[i+1]
                
            #print(diff)
                
            for i in range(len(diff)):
                #print(values)
                if diff[i] != 0:
                    #print(orders)
                    if orders >= diff[i]*(i+1):
                        values += (i+1)*self.getSum(lst[i], lst[i+1])
                        #print(lst[i], lst[i+1])
                        #print(values)
                        values %= 1000000007
                        orders -= diff[i]*(i+1)
                        #print(diff[i]*(i+1))
                        #print(orders)
                    else:
                        #print(orders)
                        high = orders // (i+1)
                        #print(high)
                        #print(lst[i], lst[i]-high)
                        values += (i+1)*self.getSum(lst[i], lst[i]-high)
                        values %= 1000000007
                        orders %= i+1
                        values += (orders)*(lst[i]-high)
                        values %= 1000000007
                        return values
            return values
        
        def getSum(self, start, end): # [start, end)
            if start < end:
                start, end = end, start
            end = end + 1 # [start, end]
            return (start + end) * (start - end + 1) // 2
    

    返回目录

    4. 通过指令创建有序数组 -- 困难

    题目链接:https://leetcode-cn.com/problems/create-sorted-array-through-instructions/

    题目描述:

    给你一个整数数组 instructions ,你需要根据 instructions 中的元素创建一个有序数组。一开始你有一个空的数组 nums ,你需要 从左到右 遍历 instructions 中的元素,将它们依次插入 nums 数组中。每一次插入操作的 代价 是以下两者的 较小值 :
    nums 中 严格小于 instructions[i] 的数字数目。
    nums 中 严格大于 instructions[i] 的数字数目。
    比方说,如果要将 3 插入到 nums = [1,2,3,5] ,那么插入操作的 代价 为 min(2, 1) (元素 1 和 2 小于 3 ,元素 5 大于 3 ),插入后 nums 变成 [1,2,3,3,5] 。
    请你返回将 instructions 中所有元素依次插入 nums 后的 总最小代价 。由于答案会很大,请将它对 109 + 7 取余 后返回。

    示例 1:
    输入:instructions = [1,5,6,2]
    输出:1
    解释:一开始 nums = [] 。
    插入 1 ,代价为 min(0, 0) = 0 ,现在 nums = [1] 。
    插入 5 ,代价为 min(1, 0) = 0 ,现在 nums = [1,5] 。
    插入 6 ,代价为 min(2, 0) = 0 ,现在 nums = [1,5,6] 。
    插入 2 ,代价为 min(1, 2) = 1 ,现在 nums = [1,2,5,6] 。
    总代价为 0 + 0 + 0 + 1 = 1 。

    示例 2:
    输入:instructions = [1,2,3,6,5,4]
    输出:3
    解释:一开始 nums = [] 。
    插入 1 ,代价为 min(0, 0) = 0 ,现在 nums = [1] 。
    插入 2 ,代价为 min(1, 0) = 0 ,现在 nums = [1,2] 。
    插入 3 ,代价为 min(2, 0) = 0 ,现在 nums = [1,2,3] 。
    插入 6 ,代价为 min(3, 0) = 0 ,现在 nums = [1,2,3,6] 。
    插入 5 ,代价为 min(3, 1) = 1 ,现在 nums = [1,2,3,5,6] 。
    插入 4 ,代价为 min(3, 2) = 2 ,现在 nums = [1,2,3,4,5,6] 。
    总代价为 0 + 0 + 0 + 0 + 1 + 2 = 3 。

    示例 3:
    输入:instructions = [1,3,3,3,2,4,2,1,2]
    输出:4
    解释:一开始 nums = [] 。
    插入 1 ,代价为 min(0, 0) = 0 ,现在 nums = [1] 。
    插入 3 ,代价为 min(1, 0) = 0 ,现在 nums = [1,3] 。
    插入 3 ,代价为 min(1, 0) = 0 ,现在 nums = [1,3,3] 。
    插入 3 ,代价为 min(1, 0) = 0 ,现在 nums = [1,3,3,3] 。
    插入 2 ,代价为 min(1, 3) = 1 ,现在 nums = [1,2,3,3,3] 。
    插入 4 ,代价为 min(5, 0) = 0 ,现在 nums = [1,2,3,3,3,4] 。
    ​​​​​插入 2 ,代价为 min(1, 4) = 1 ,现在 nums = [1,2,2,3,3,3,4] 。
    插入 1 ,代价为 min(0, 6) = 0 ,现在 nums = [1,1,2,2,3,3,3,4] 。
    插入 2 ,代价为 min(2, 4) = 2 ,现在 nums = [1,1,2,2,2,3,3,3,4] 。
    总代价为 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 2 = 4 。

    提示:
    1 <= instructions.length <= 105
    1 <= instructions[i] <= 105

    解题思路:

    用dic存储,然后遍历一下,找出其中比当前值小的和大的。
    不过这种遍历算法会超时,需要进一步优化。

    代码:

    class Solution:
        def createSortedArray(self, instructions: List[int]) -> int:
            dic = {}
            cnt = 0
            for i in range(len(instructions)):
                num = instructions[i]
                big = 0
                small = 0
                for k, v in dic.items():
                    if k < num:
                        small += v
                    if k > num:
                        big += v
                    
                if num not in dic:
                    dic[num] = 0
                dic[num] += 1
                cnt += min(big, small)
                cnt %= 1000000007
            return cnt
    

    返回目录

    2020年11月28日 -- 双周赛

    做对了三道,最后一道有点复杂,没时间写了。

    1. 最大重复子字符串 -- 简单

    题目链接:https://leetcode-cn.com/problems/maximum-repeating-substring/

    题目描述

    给你一个字符串 sequence ,如果字符串 word 连续重复 k 次形成的字符串是 sequence 的一个子字符串,那么单词 word 的 重复值为 k 。
    单词 word 的 最大重复值 是单词 word 在 sequence 中最大的重复值。如果 word 不是 sequence 的子串,那么重复值 k 为 0 。

    给你一个字符串 sequence 和 word ,请你返回 最大重复值 k 。

    示例 1:
    输入:sequence = "ababc", word = "ab"
    输出:2
    解释:"abab" 是 "ababc" 的子字符串。

    示例 2:
    输入:sequence = "ababc", word = "ba"
    输出:1
    解释:"ba" 是 "ababc" 的子字符串,但 "baba" 不是 "ababc" 的子字符串。

    示例 3:
    输入:sequence = "ababc", word = "ac"
    输出:0
    解释:"ac" 不是 "ababc" 的子字符串。
     
    提示:
    1 <= sequence.length <= 100
    1 <= word.length <= 100
    sequence 和 word 都只包含小写英文字母。

    解题思路

    字符串匹配问题,只不过word可以循环多次。

    代码

    class Solution:
        def maxRepeating(self, sequence: str, word: str) -> int:
            len_s = len(sequence)
            len_w = len(word)
            index = 0
            max_cnt = 0
            
            for i in range(len_s):
                while i+index < len_s and sequence[i+index] == word[index%len_w]:
                    index += 1
                temp_cnt = index // len_w
                if temp_cnt > max_cnt:
                    max_cnt = temp_cnt
                index = 0
                
            return max_cnt
    

    返回目录

    2. 合并两个链表 -- 中等

    题目链接:https://leetcode-cn.com/problems/merge-in-between-linked-lists/

    题目描述

    给你两个链表 list1 和 list2 ,它们包含的元素分别为 n 个和 m 个。
    请你将 list1 中第 a 个节点到第 b 个节点删除,并将list2 接在被删除节点的位置。
    请你返回结果链表的头指针。

    示例 1:
    输入:list1 = [0,1,2,3,4,5], a = 3, b = 4, list2 = [1000000,1000001,1000002]
    输出:[0,1,2,1000000,1000001,1000002,5]
    解释:我们删除 list1 中第三和第四个节点,并将 list2 接在该位置。上图中蓝色的边和节点为答案链表。

    示例 2:
    输入:list1 = [0,1,2,3,4,5,6], a = 2, b = 5, list2 = [1000000,1000001,1000002,1000003,1000004]
    输出:[0,1,1000000,1000001,1000002,1000003,1000004,6]
    解释:上图中蓝色的边和节点为答案链表。

    提示:
    3 <= list1.length <= 104
    1 <= a <= b < list1.length - 1
    1 <= list2.length <= 104

    解题思路:

    链表操作问题,比较简单。

    代码:

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def mergeInBetween(self, list1: ListNode, a: int, b: int, list2: ListNode) -> ListNode:
            index = 0
            leftNode = list1
            rightNode = list1
            while index <= b:
                if index < a-1:
                    leftNode = leftNode.next
                if index <= b:
                    rightNode = rightNode.next
                index += 1
                    
            leftNode.next = list2
            
            list2_tail = list2
            while list2_tail.next is not None:
                list2_tail = list2_tail.next
            
            list2_tail.next = rightNode
            
            return list1
    

    返回目录

    3. 设计前中后队列 -- 中等

    题目链接:https://leetcode-cn.com/problems/design-front-middle-back-queue/

    题目描述:

    请你设计一个队列,支持在前,中,后三个位置的 push 和 pop 操作。

    请你完成 FrontMiddleBack 类:

    FrontMiddleBack() 初始化队列。
    void pushFront(int val) 将 val 添加到队列的 最前面 。
    void pushMiddle(int val) 将 val 添加到队列的 正中间 。
    void pushBack(int val) 将 val 添加到队里的 最后面 。
    int popFront() 将 最前面 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 。
    int popMiddle() 将 正中间 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 。
    int popBack() 将 最后面 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 。
    请注意当有 两个 中间位置的时候,选择靠前面的位置进行操作。比方说:

    将 6 添加到 [1, 2, 3, 4, 5] 的中间位置,结果数组为 [1, 2, 6, 3, 4, 5] 。
    从 [1, 2, 3, 4, 5, 6] 的中间位置弹出元素,返回 3 ,数组变为 [1, 2, 4, 5, 6] 。
     
    示例 1:
    输入:
    ["FrontMiddleBackQueue", "pushFront", "pushBack", "pushMiddle", "pushMiddle", "popFront", "popMiddle", "popMiddle", "popBack", "popFront"]
    [[], [1], [2], [3], [4], [], [], [], [], []]

    输出:
    [null, null, null, null, null, 1, 3, 4, 2, -1]

    解释:
    FrontMiddleBackQueue q = new FrontMiddleBackQueue();
    q.pushFront(1); // [1]
    q.pushBack(2); // [1, 2]
    q.pushMiddle(3); // [1, 3, 2]
    q.pushMiddle(4); // [1, 4, 3, 2]
    q.popFront(); // 返回 1 -> [4, 3, 2]
    q.popMiddle(); // 返回 3 -> [4, 2]
    q.popMiddle(); // 返回 4 -> [2]
    q.popBack(); // 返回 2 -> []
    q.popFront(); // 返回 -1 -> [] (队列为空)

    提示:
    1 <= val <= 109
    最多调用 1000 次 pushFront, pushMiddle, pushBack, popFront, popMiddle 和 popBack 。

    解题思路:

    Python类操作及数组插入删除题。

    代码:

    class FrontMiddleBackQueue:
    
        def __init__(self):
            self.data = []
    
        def pushFront(self, val: int) -> None:
            self.data.append(val)
            cnt = len(self.data) - 1
            while cnt >= 1:
                self.swap(cnt-1, cnt)
                cnt -= 1
            #print(self.data)
    
        def pushMiddle(self, val: int) -> None:
            self.data.append(val)
            cnt = len(self.data) - 1
            while cnt > (len(self.data)+1)//2 - 1:
                self.swap(cnt-1, cnt)
                cnt -= 1
            #print(self.data)
    
        def pushBack(self, val: int) -> None:
            self.data.append(val)
            #print(self.data)
    
        def popFront(self) -> int:
            if len(self.data) == 0:
                return -1
            rst = (self.data)[0]
            self.data = (self.data)[1:]
            #print(self.data)
            return rst
    
        def popMiddle(self) -> int:
            if len(self.data) == 0:
                return -1
            cnt = (len(self.data)+1)//2 - 1
            while cnt < len(self.data)-1:
                self.swap(cnt, cnt+1)
                cnt += 1
            rst = (self.data)[-1]
            self.data = (self.data)[:-1]
            #print(self.data)
            return rst
    
        def popBack(self) -> int:
            if len(self.data) == 0:
                return -1
            rst = (self.data)[-1]
            self.data = (self.data)[:-1]
            #print(self.data)
            return rst
            
        def swap(self, a, b):
            temp = (self.data)[a]
            (self.data)[a] = (self.data)[b]
            (self.data)[b] = temp
    
    
    # Your FrontMiddleBackQueue object will be instantiated and called as such:
    # obj = FrontMiddleBackQueue()
    # obj.pushFront(val)
    # obj.pushMiddle(val)
    # obj.pushBack(val)
    # param_4 = obj.popFront()
    # param_5 = obj.popMiddle()
    # param_6 = obj.popBack()
    

    返回目录

  • 相关阅读:
    vba中数据类型
    Excel统计函数COUNTIF()的常规用法介绍
    分类求和
    在每个sheet的相同位置写入相同的值
    Timer函数
    数组总结
    如何制作本地yum源
    HDFS的优缺点
    HDFS安全模式
    HDFS的HA(高可用)
  • 原文地址:https://www.cnblogs.com/yanqiang/p/13685833.html
Copyright © 2011-2022 走看看