• leetcode刷题 373~


    题目373题

    查找和最小的k对数字

    给定两个以升序排列的整形数组 nums1 和 nums2, 以及一个整数 k。

    定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2。

    找到和最小的 k 对数字 (u1,v1), (u2,v2) ... (uk,vk)。

    示例 1:

    输入: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
    输出: [1,2],[1,4],[1,6]
    解释: 返回序列中的前 3 对数:
    [1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]

    思路

    1.暴力法,取出所有数字排序

    2.优先队列:

    将数组1作为base,滑动数组2。每将一对作为结果输出时,将下一对加入队列中,若选择的这对位于数组2的开始,则将数组1滑动1位加入队列

    实现

    class Solution:
        def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
            """
            数组1作为base,滑动数组2
            """
            heap = []
            def push(i, j):
                if i < len(nums1) and j < len(nums2):
                    heapq.heappush(heap, [nums1[i] + nums2[j], i, j])
            push(0,0)
            result = []
            while heap and len(result) < k:
                pair, i, j = heapq.heappop(heap)
                result.append([nums1[i], nums2[j]])
                push(i,j+1)
                if j == 0:
                    push(i + 1, 0)
            return result

    题目374题

    猜数字大小

    猜数字游戏的规则如下:

    每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。
    如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。
    你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):

    -1:我选出的数字比你猜的数字小 pick < num
    1:我选出的数字比你猜的数字大 pick > num
    0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num

    思路

    二分法

    实现

    class Solution:
        def guessNumber(self, n: int) -> int:
            left ,right = 1, n
            while left <= right:
                testcase = (left+right)//2
                result = guess(testcase)
                if  result == 0:
                    return testcase
                elif result == 1:
                    left = testcase+1
                else:
                    right = testcase-1

    题目376题

    摆动序列

    如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。

    例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

    给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。

    思路

    动态规划:维护一个增序列和一个减序列

    实现

    class Solution:
        def wiggleMaxLength(self, nums: List[int]) -> int:
            if len(nums) <2:
                return len(nums)
            up, down = 1, 1
            for i in range(1, len(nums)):
                if nums[i] > nums[i-1]:
                    up = down + 1
                elif nums[i] < nums[i-1]:
                    down = up+1
            return max(up,down)

    题目377题

    组合总和IV

    思路

    1.递归:时间复杂度 O(target*n) 空间复杂度O(max(n,target))

    2.动态规划O(n)

    实现

    1.
    class Solution:
        def combinationSum4(self, nums: List[int], target: int) -> int:
            result = 0
            @functools.lru_cache(None)
            def combination(target):
                if target == 0:
                    return 1
                elif target < 0:
                    return 0
                ans = 0
                for num in nums:
                    ans += combination(target-num)
                return ans
            return combination(target)
    2.
    class Solution:
        def combinationSum4(self, nums: List[int], target: int) -> int:
            dp = [0 for _ in range(target+1)]
            dp[0] = 1
            for i in range(1,target+1):
                for num in nums:
                    if i >= num:
                        dp[i] += dp[i-num]
            return dp[target]

    题目378题

    有序矩阵中第K小的元素

    思路

    1.优先队列:与373题完全相同

    2.二分法

    实现

    1.
    class Solution:
        def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
            heap = []
            n = len(matrix)
            def push(i, j):
                if i < n  and j < n:
                    heapq.heappush(heap, [matrix[i][j], i, j])
            push(0,0)
            key  = 1
            while heap and key <= k:
                val, i ,j = heapq.heappop(heap)
                key += 1
                push(i, j+1)
                if j == 0:
                    push(i+1, 0)
            return val
    2.
    class Solution:
        def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
            n = len(matrix)
            def check(val):
                i, j = n-1, 0
                num = 0
                while i >=0 and j < n:
                    if matrix[i][j] <= mid:
                        j+=1
                        num += i + 1
                    else:
                        i -= 1
                return num >=k
            left, right = matrix[0][0], matrix[n-1][n-1]
            while left < right:
                mid = left + (right-left)//2
                if check(mid):
                    right = mid
                else:
                    left = mid + 1
            return left     

    题目380题

    常数时间插入、删除、获取随机数

    思路

    数组+哈希表

    实现

    class RandomizedSet:
    
        def __init__(self):
            """
            Initialize your data structure here.
            """
            self.randomset = list()
            self.dic = dict()
    
        def insert(self, val: int) -> bool:
            """
            Inserts a value to the set. Returns true if the set did not already contain the specified element.
            """
            if val in self.dic:
                return False
            self.dic[val] = len(self.randomset)
            self.randomset.append(val)
            return True
    
    
        def remove(self, val: int) -> bool:
            """
            Removes a value from the set. Returns true if the set contained the specified element.
            """
            if val not in self.dic:
                return False
            index = self.dic[val]
            last = self.randomset[-1]
            self.randomset[index] = last
            self.dic[last] = index
            self.dic.pop(val)
            self.randomset.pop()
            return True
    
    
        def getRandom(self) -> int:
            """
            Get a random element from the set.
            """
            whole = len(self.randomset)
            index = random.randint(0,whole-1)
            return self.randomset[index]

    题目382题

    链表随机节点

    思路

    1.数组,将链表放入数组中,然后取数组的随机点,但是这样空间复杂度为O(n)

    2.蓄水池抽样算法

    实现

    class Solution:
    
        def __init__(self, head: ListNode):
            """
            @param head The linked list's head.
            Note that the head is guaranteed to be not null, so it contains at least one node.
            """
            self.head = head
    
        def getRandom(self) -> int:
            """
            Returns a random node's value.
            """
            count = 0
            head = self.head
            while head:
                count += 1
                rand = random.randint(1,count)
                if rand == count:
                    result = head.val
                head = head.next
            return result

    题目367题

    赎金信

    给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。

    思路实现

    class Solution:
        def canConstruct(self, ransomNote: str, magazine: str) -> bool:
            ransom = dict()
            for alpha in ransomNote:
                ransom[alpha] = ransom.get(alpha,0) + 1
            for alpha in magazine:
                ransom[alpha] = ransom.get(alpha,0) - 1
            for item in ransom:
                if ransom[item] > 0 :
                    return False
            return True

    题目384题

    打乱数组

    给你一个整数数组 nums ,设计算法来打乱一个没有重复元素的数组。

    实现 Solution class:

    Solution(int[] nums) 使用整数数组 nums 初始化对象
    int[] reset() 重设数组到它的初始状态并返回
    int[] shuffle() 返回数组随机打乱后的结果

    思路实现

    class Solution:
    
        def __init__(self, nums: List[int]):
            self.nums = nums
            self.original = list(nums)
    
        def reset(self) -> List[int]:
            """
            Resets the array to its original configuration and return it.
            """
            self.nums = self.original
            self.original = list(self.original)
            return self.nums
    
        def shuffle(self) -> List[int]:
            """
            Returns a random shuffling of the array.
            """
            count = len(self.nums)
            for i in range(count):
                rand1 = random.randint(0,count-1)
                self.nums[rand1], self.nums[i] = self.nums[i], self.nums[rand1]
            return self.nums

    题目385题

    迷你语法分析器

    给定一个用字符串表示的整数的嵌套列表,实现一个解析它的语法分析器。

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

    提示:你可以假定这些字符串都是格式良好的:

    字符串非空
    字符串不包含空格
    字符串只包含数字0-9、[、-、,、]

    思路

    1.栈,遇见"[",则建立NestedInteger对象,并入栈,遇见","or"]",则添加数据,遇见"]"出栈并添加进入栈顶元素队列中

    2.递归

    实现

    1.
    class Solution:
        def deserialize(self, s: str) -> NestedInteger:
            if s[0] != "[":
                return NestedInteger(int(s))
            num, sign,is_num = 0 ,1, False
            stack = []
            for i in s:
                if i.isdigit():
                    num = int(i) + num*10
                    is_num = True
                elif i == "-":
                    sign = -1
                elif i == "[":
                    stack.append(NestedInteger())
                elif i == "," or i == "]" :
                    if is_num:
                        cur = stack.pop()
                        cur.add(NestedInteger(sign*num))
                        stack.append(cur)
                    num, sign,is_num = 0 ,1, False
                if i == "]" and len(stack) > 1:
                    cur = stack.pop()
                    stack[-1].add(cur)
            return stack[0]
    2.
    class Solution:
        def deserialize(self, s: str) -> NestedInteger:
            if s[0] != "[":
                return NestedInteger(int(s))
            self.idx = 0
            self.n = len(s)
            self.s = s
            return self.__deserialize()
        def __deserialize(self) -> NestedInteger:
            nested = NestedInteger()
            num, sign = 0, 1
            while self.idx < self.n:
                self.idx += 1
                if self.s[self.idx] == ",":
                    continue
                elif self.s[self.idx] == "[":
                    nested.add(self.__deserialize())
                elif self.s[self.idx] == "]":
                    return nested
                elif self.s[self.idx] == "-":
                    sign = -1
                else:
                    num = num*10 + int(self.s[self.idx])
                    if self.s[self.idx+1] == "," or self.s[self.idx+1] == "]":
                        nested.add(NestedInteger(sign*num))
                        num,sign = 0, 1

    题目386题

    字典序排数

    给定一个整数 n, 返回从 1 到 n 的字典顺序。

    例如,

    给定 n =1 3,返回 [1,10,11,12,13,2,3,4,5,6,7,8,9] 。

    请尽可能的优化算法的时间复杂度和空间复杂度。 输入的数据 n 小于等于 5,000,000。

    思路

    1.动态规划和栈:

    有三种情况:

    当前数等于上一个数乘以10,上一个数入栈;当前数等于上一个数+1;当前数等于栈顶数+1

    2.深度优先遍历

    实现

    class Solution:
        def lexicalOrder(self, n: int) -> List[int]:
            dp = [1 for _ in range(n+1)]
            stack = [0]
            for i in range(1,n):
                if dp[i] *10 <= n:
                    dp[i+1] = dp[i]*10
                    stack.append(dp[i])
                elif dp[i] + 1 < (stack[-1]+1)*10 and dp[i]+1 <= n:
                    dp[i+1] = dp[i] + 1
                else:
                    while stack:
                        sigh = stack.pop()
                        if sigh + 1 < (stack[-1]+1)*10:
                            dp[i+1] = sigh + 1
                            break
            return dp[1:]
    class Solution:
        def lexicalOrder(self, n: int) -> List[int]:
            result = []
            def dfs(num):
                if num >n:
                    return
                result.append(num)
                for i in range(0,10):
                    dfs(num*10 + i)
            for i in range(1,10):
                dfs(i)
            return result

    题目387题

    字符串中的第一个唯一字符

    给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

    思路实现

    class Solution:
        def firstUniqChar(self, s: str) -> int:
            result = [-1 for _ in range(26)]
            for i in range(len(s)):
                idx = ord(s[i]) - 97
                if result[idx] == -1:
                    result[idx] = i
                elif result[idx] >= 0:
                    result[idx] = -2
            res = len(s)
            for i in result:
                if i >= 0:
                    res = min(i,res)
            return res if res < len(s) else -1

    题目388题

    文件的最长绝对路径

    思路实现

    class Solution:
        def lengthLongestPath(self, input: str) -> int:
    
            input = input.split("
    ")
            dirindex = []
            result = []
            res = [0]
    
            def read(index):
                s = input[index]
                cur = s.count("	")
                filelen = len(s) - cur
                # 寻找上级目录
                last = cur - 1
                lastlen = 0
                if last >= 0:
                    for i in range(len(dirindex)-1,-1,-1):
                        if dirindex[i] == last:
                            lastlen = result[i] + 1
                            break
                dirindex.append(cur)
                result.append(filelen+lastlen)
                if "." in s:
                    res.append(filelen+lastlen)
            for i in range(len(input)):
                read(i)
            return max(res)

    题目389题

    找不同

    给定两个字符串 s 和 t,它们只包含小写字母。

    字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。

    请找出在 t 中被添加的字母。

    思路

    字符串的ascii码之和 的差就是多出的字符

    实现

    class Solution:
        def findTheDifference(self, s: str, t: str) -> str:
            return chr(sum(map(ord, t)) - sum(map(ord, s)))

    题目390题

    消除游戏

    给定一个从1 到 n 排序的整数列表。
    首先,从左到右,从第一个数字开始,每隔一个数字进行删除,直到列表的末尾。
    第二步,在剩下的数字中,从右到左,从倒数第一个数字开始,每隔一个数字进行删除,直到列表开头。
    我们不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。
    返回长度为 n 的列表中,最后剩下的数字。

    思路

    递归:

    f(2k)=2(k+1f(k))

    实现

    class Solution:
        def lastRemaining(self, n: int) -> int:
            return 1 if n==1 else 2*(n//2 + 1- self.lastRemaining(n//2))

    题目392题

    判断子序列

    给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

    你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。

    字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

    思路

    贪心算法:从前往后匹配,可以发现每次贪心地匹配靠前的字符是最优决策。

    实现

    class Solution:
        def isSubsequence(self, s: str, t: str) -> bool:
            indx = 0
            l = len(s)
            if not s:
                return True
            for i in t:
                if i == s[indx]:
                    indx += 1
                if indx == l:
                    return True
            return False

    题目393题

    UTF-8编码验证

    UTF-8 中的一个字符可能的长度为 1 到 4 字节,遵循以下的规则:

    对于 1 字节的字符,字节的第一位设为0,后面7位为这个符号的unicode码。
    对于 n 字节的字符 (n > 1),第一个字节的前 n 位都设为1,第 n+1 位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

    思路实现

    class Solution:
        def validUtf8(self, data: List[int]) -> bool:
            check = 0
            for num in data:
                if num == 255:
                    return False
                bin_num = '{:08b}'.format(num)
                zero = bin_num.index('0')
                if check == 0:
                    if zero == 0:
                        continue
                    check += zero
                    if check == 1 or check >4:
                        return False
                else:
                    if zero != 1:
                        return False
                check -= 1
            return check == 0

    题目394题

    字符串解码

    给定一个经过编码的字符串,返回它解码后的字符串。

    编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

    你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

    此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

    思路

    栈实现

    实现

    class Solution:
        def decodeString(self, s: str) -> str:
            num = 0
            substring = ""
            num_stack = []
            string_stack = []
            result = ""
            for index in range(len(s)):
                i = s[index]
                if i.isdigit():
                    num = num*10 + int(i)
                elif i.isalpha():
                    string_stack.append(i)
                    num_stack.append(1)
                if i == "[":
                    num_stack.append(num)
                    string_stack.append("")
                    num = 0
                elif i == "]":
                    temp = ""
                    while string_stack:
                        if string_stack[-1] != "":
                            temp = num_stack.pop()*string_stack.pop()+temp
                        else:
                            temp = num_stack.pop()*(string_stack.pop()+temp)
                            break
                    string_stack.append(temp)
                    num_stack.append(1)
                if index == len(s)-1:
                    for string in string_stack:
                        result += string
            return result

    题目395题

    至少有k个重复字符的最长子串

    找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 的长度。

    思路

    将次数不足k的字符做为分隔符进行分割,对分割后的子串t递归调用函数,返回满足题目要求的最长子串长度

    实现

    class Solution:
        def longestSubstring(self, s: str, k: int) -> int:
            if len(s) < k:
                return 0
            for alpha in set(s):
                if s.count(alpha) < k:
                    return max(self.longestSubstring(sub, k) for sub in s.split(alpha))
            return len(s)
  • 相关阅读:
    移动端hybrid开发复盘
    node/webpack 调试 loader 等技巧
    javascript(js)小数精度丢失的解决方案
    必经之路--买房之后需要走的流程--针对 组合贷款方式
    canvas 画半圆的两种方式
    svg path 画圆
    1.快速排序
    7.桥接设计模式
    6.适配器设计模式
    5.策略设计模式
  • 原文地址:https://www.cnblogs.com/mgdzy/p/13914220.html
Copyright © 2020-2023  润新知