zoukankan      html  css  js  c++  java
  • leetcode刷题 396~

    题目396题

    旋转函数

    给定一个长度为 n 的整数数组 A 。

    假设 Bk 是数组 A 顺时针旋转 k 个位置后的数组,我们定义 A 的“旋转函数” F 为:

    F(k) = 0 * Bk[0] + 1 * Bk[1] + ... + (n-1) * Bk[n-1]。

    计算F(0), F(1), ..., F(n-1)中的最大值。

    思路实现

    class Solution:
        def maxRotateFunction(self, A: List[int]) -> int:
            if not A:
                return 0
            s,f0, l = 0, 0, len(A)
            for i in range(l):
                f0 += i * A[i]
                s += A[i]
            result = float("-inf")
            for i in range(l-1, -1, -1):
                f0 = f0 - l*A[i] + s
                result = max(result, f0)
            return result

    题目397题

    整数替换

    思路

    1.动态规划:居然超时了

    2.记忆化递归:

    • @lru_cache(None)Python标准库,用于缓存

    实现

    1.
    class Solution:
        def integerReplacement(self, n: int) -> int:
            if n == 1:
                return 0
            dp = [0 for _ in range(n+4)]
            dp[1],dp[2] = 0,1
            i = 4
            while dp[n] == 0:
                if i % 2 == 0:
                    dp[i] = dp[i//2] + 1
                    i -= 1
                elif i % 2 == 1:
                    dp[i] = min(dp[i+1],dp[i-1]) + 1
                    i += 3
            return dp[n]
    2.
    class Solution:
        def integerReplacement(self, n: int) -> int:
            @lru_cache(None)
            def dfs(n):
                if n==1:
                    return 0
    
                ans=0
                if n&1:
                    ans+=1+min(dfs(n+1),dfs(n-1))
                else:
                    ans+=1+dfs(n//2)
                return ans
            
            return dfs(n)

    题目398题

    随机数索引

    思路

    1.字典:在初始化中建立字典,键为元素的值,值为元素索引组成的数组

    2.蓄水池抽样

    实现

    class Solution:
    
        def __init__(self, nums: List[int]):
            self.dic =dict()
            for idx in range(len(nums)):
                self.dic.setdefault(nums[idx], []).append(idx)
    
    
        def pick(self, target: int) -> int:
            temp = self.dic[target]
            ran = random.randint(0,len(temp)-1)
            return temp[ran]
    2.
    class Solution:

        def __init__(self, nums: List[int]):
            self.nums = nums


        def pick(self, target: int) -> int:
            count = 0
            for idx in range(len(self.nums)):
                if self.nums[idx] == target:
                    if random.randint(0,count) == 0:
                        result = idx
                    count += 1
            return result

    题目399题

    除法求值

    给出方程式 A / B = k, 其中 A 和 B 均为用字符串表示的变量, k 是一个浮点型数字。根据已知方程式求解问题,并返回计算结果。如果结果不存在,则返回 -1.0。

    输入总是有效的。你可以假设除法运算中不会出现除数为 0 的情况,且不存在任何矛盾的结果。

    思路

    深度优先遍历:先构造图,然后深度优先遍历

    实现

    class Solution:
        def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
            graph = {}
            for (x, y), v in zip(equations, values):
                if x in graph:
                    graph[x][y] = v
                else:
                    graph[x] = {y: v}
                if y in graph:
                    graph[y][x] = 1/v
                else:
                    graph[y] = {x: 1/v}
            def dfs(qs, qt)->int:
                if qs not in graph:
                    return -1
                if qs == qt:
                    return 1
                for node in graph[qs].keys():
                    if node == qt:
                        return graph[qs][node]
                    elif node not in visited:
                        visited.add(node)
                        value = dfs(node,qt)
                        if value != -1:
                            return graph[qs][node]*value
                return -1
            result = []
            for qs, qt in queries:
                visited = set()
                result.append(dfs(qs, qt))
            return result

    题目400题

    第N个数字

    在无限的整数序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...中找到第 个数字。

    思路

    首先确定这个数的长度,根据长度来确实结束时的数的大小,然后判断是这个数字的第几位,最后返回结果

    实现

    class Solution:
        def findNthDigit(self, n: int) -> int:
            wei= 1
            index = wei * 9 * (10**(wei-1))
            while n > index:
                n -= index
                wei += 1
                index = wei * 9 * (10**(wei-1))
            num = (10**(wei-1)) + (n-1)//wei
            remain = (n-1)%wei
            numstr = str(num)
            return numstr[remain]

    题目401题

    二进制手表

    二进制手表顶部有 4 个 LED 代表 小时(0-11),底部的 6 个 LED 代表 分钟(0-59)。每个 LED 代表一个 0 或 1,最低位在右侧。

    示例:

    输入: n = 1
    返回: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]

    思路

    分别计算小时和分钟

    实现

    class Solution:
        def readBinaryWatch(self, num: int) -> List[str]:
            hour_result = []
            min_result = []
            def dfs(wei,num,res,sigh):
                if wei == 0 and num ==0:
                    if sigh == True:
                        if res < 12:
                            hour_result.append(res)
                    else:
                        if res <60:
                            min_result.append(res)
                elif wei <= 0:
                    return 0
                for i in range(2):
                    if i == 0:
                        dfs(wei-1,num,res,sigh)
                    else:
                        dfs(wei-1,num-1,res+2**(wei-1),sigh)
            result = []
            for hour in range(num+1):
                hour_result = []
                min_result = []
                dfs(4,hour,0,True)
                dfs(6,num-hour,0,False)
                for i in hour_result:
                    for j in min_result:
                        temp = str(i) + ":"
                        temp += str(j) if j>=10 else "0"+str(j)
                        result.append(temp)
            return result

    题目402题

    移掉K位数字

    给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。

    注意:

    num 的长度小于 10002 且 ≥ k。
    num 不会包含任何前导零。

    思路

    给定一个数字序列 [D1D2D3…Dn] ,如果数字 D2 < D1,则我们应该删除左邻居D1,以获得最小结果。

    实现

    class Solution:
        def removeKdigits(self, num: str, k: int) -> str:
            result = []
            for i in num:
                while result and k and result[-1] > i:
                    result.pop()
                    k -= 1
                result.append(i)
            result = result[:-k] if k else result
            return "".join(result).lstrip('0') or "0"

    题目404题

    左叶子之和

    计算给定二叉树的所有左叶子之和。

    思路实现

    class Solution:
        def sumOfLeftLeaves(self, root: TreeNode) -> int:
            
            def sumofleavse(node, sigh):
                val = 0
                if not node:
                    return val
                if node.left:
                    val += sumofleavse(node.left, True)
                if node.right:
                    val += sumofleavse(node.right, False)
                if not node.left and not node.right and sigh:
                    val += node.val
                return val
    
            return sumofleavse(root,False)

    题目405题

    数字转换为十六进制

    给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。

    思路

    主要是理解补码:

    num = (abs(num) ^ ((2 ** 32) - 1)) + 1

    实现

    class Solution:
        def toHex(self, num: int) -> str:
            hexnum = "0123456789abcdef"
            def get(num):
                result = ""
                while num != 0:
                    i = num % 16
                    result = hexnum[i] + result
                    num = num // 16
                return result
            if num < 0:
                num = (abs(num) ^ ((2 ** 32) - 1)) + 1
            elif num ==0:
                return "0"
            return get(num)

    题目406题

    根据身高重建队列

    假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数。 编写一个算法来重建这个队列。

    注意:
    总人数少于1100人。

    示例

    输入:
    [[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]

    输出:
    [[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]

    思路

    没有做出来,查看解答后发现是利用的贪心算法,利用矮的人相对于高的人是看不见的:因为k的值是前面比自己高或等高的人的个数。先处理高的人,满足k的条件后,再处理矮的人是不会破坏这个条件的。

    算法:

    • 排序:
      • 按高度降序排列。
      • 在同一高度的人中,按 k 值的升序排列。
    • 逐个地把它们放在输出队列中,索引等于它们的 k 值。
    • 返回输出队列

    实现

    class Solution:
        def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
            people = sorted(people, key = lambda x: (-x[0], x[1]))
            result =[]
            for i in people:
                result.insert(i[1],i)
            return result

    题目395题

    最长回文串

    给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。

    在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。

    思路实现

    class Solution:
        def longestPalindrome(self, s: str) -> int:
            dic = dict()
            for i in s:
                dic[i] = dic.get(i,0) + 1
            result,sign = 0, 0
            for i in dic:
                num = dic[i]//2
                if num >= 1:
                    result += num*2
                if dic[i]%2 == 1:
                    sign = 1
            return result+sign

    题目412题

    FizzBuzz

    写一个程序,输出从 1 到 n 数字的字符串表示。

    1. 如果 n 是3的倍数,输出“Fizz”;

    2. 如果 n 是5的倍数,输出“Buzz”;

    3.如果 n 同时是3和5的倍数,输出 “FizzBuzz”。

    思路实现

    class Solution:
        def fizzBuzz(self, n: int) -> List[str]:
            result = ["" for _ in range(n)]
            for i in range(n):
                temp = i+1
                if temp%3 == 0:
                    result[i] += "Fizz"
                if temp%5 == 0:
                    result[i] += "Buzz"
                if result[i] == "": 
                    result[i] += str(temp)
            return result

    题目414题

    第三大的数

    思路实现

    class Solution:
        def thirdMax(self, nums: List[int]) -> int:
            first, second, third = float("-inf"), float("-inf"),float("-inf")
            for num in nums:
                if num > first:
                    third,second = second,first
                    first = num
                elif num == first:
                    continue
                elif num > second:
                    third = second
                    second = num
                elif num == second:
                    continue
                elif num > third:
                    third = num
            if third != float("-inf"):
                return third
            else:
                return first

    题目395题

    字符串相加

    思路实现

    class Solution:
        def addStrings(self, num1: str, num2: str) -> str:
            index1, index2, add = len(num1)-1, len(num2)-1, 0
            result = ""
            while index1 >= 0 or index2 >=0 or add != 0:
                x = int(num1[index1]) if index1 >= 0 else 0
                y = int(num2[index2]) if index2 >= 0 else 0
                temp = x + y + add
                result = str(temp%10) + result
                add = temp//10
                index1 -= 1
                index2 -= 1
            return result

    题目417题

    太平洋大西洋水流问题

    给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。

    规定水流只能按照上、下、左、右四个方向流动,且只能从高到低或者在同等高度上流动。

    请找出那些水流既可以流动到“太平洋”,又能流动到“大西洋”的陆地单元的坐标。

    思路

    深度优先遍历:最开始的时候期望正向流动来解决问题,但是遇到了许多问题:1.从不同的位置去访问同一个位置可能结果不同2.无法控制是否访问过(如果访问过就不再访问会漏解)

    因此只能使用反向流动的方式来解决问题。以太平洋为例,从太平洋的边界向内遍历(按题目要求需要大于等于高度),如果能够遍历到说明在太平洋的界内;大西洋同理。大西洋和太平洋的交集就是最后的结果。

    实现

    class Solution:
        def pacificAtlantic(self, matrix: List[List[int]]) -> List[List[int]]:
            if not matrix or len(matrix) == 0:
                return []
            row, col = len(matrix), len(matrix[0])
            visied = [[0 for _ in range(col)] for _ in range(row)]
            a = [[0 for _ in range(col)] for _ in range(row)]
            p = [[0 for _ in range(col)] for _ in range(row)]
            move = [(0,1),(0,-1),(1,0),(-1,0)]
            result  = list()
            def dfs(i, j,temp):
                temp[i][j] = 1
                for x, y in move:
                    ni,nj = i + x, j+y
                    if 0<= ni < row and 0<= nj < col and matrix[i][j] <= matrix[ni][nj] and temp[ni][nj] != 1:
                        dfs(ni,nj,temp)
    
            for i in range(col):
                dfs(0, i, p)
                dfs(row-1, i, a)
            for i in range(row):
                dfs(i, 0 , p)
                dfs(i, col-1, a)
            for i in range(row):
                for j in range(col):
                    if a[i][j] * p[i][j]:
                        result.append([i,j])
            return result

    题目416题

    分割等和子集

    给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

    注意:

    每个数组中的元素不会超过 100
    数组的大小不会超过 200
    示例 1:

    输入: [1, 5, 11, 5]

    输出: true

    解释: 数组可以分割成 [1, 5, 5] 和 [11].

    思路

    动态规划:背包问题,详细见背包问题九讲。

    实现

    class Solution:
        def canPartition(self, nums: List[int]) -> bool:
            total = sum(nums)
            if total%2 !=0:
                return False
            half = total//2
            dp = [[False for _ in range(half+1)] for _ in range(len(nums))]
            for i in range(len(nums)):
                for j in range(0,half+1):
                    if nums[i] == j:
                        dp[i][j] = True
                        continue
                    if nums[i] < j:
                        dp[i][j] = dp[i-1][j] or dp[i-1][j-nums[i]]
            return dp[-1][half] 
    class Solution:
        def canPartition(self, nums: List[int]) -> bool:
            total = sum(nums)
            if total%2 !=0:
                return False
            half = total//2
            dp = [False for _ in range(half+1)]
            for i in range(len(nums)):
                for j in range(half,-1,-1):
                    if nums[i] == j:
                        dp[j] = True
                        continue
                    if nums[i] < j:
                        dp[j] = dp[j] or dp[j-nums[i]]
                print(dp)
            return dp[half]

    题目419题

    甲板上的战舰

    思路

    1.深度优先遍历

    2.在进阶中要求扫描一次,且空间复杂度为O(n),因此只计算战舰头,若遇到x,其左边或者上面有x,则不计算

    实现

    class Solution:
        def countBattleships(self, board: List[List[str]]) -> int:
            count = 0
            row, col = len(board), len(board[0])
            def dfs(i,j):
                if board[i][j] == ".":
                    return
                elif board[i][j] == "!":
                    return
                elif board[i][j] == "X":
                    board[i][j] = "!"
                    if 0<= i+1 < row and 0<= j < col and board[i+1][j] == "X":
                        dfs(i+1,j)
                    elif 0<= i < row and 0<= j+1 < col and board[i][j+1] == "X":
                        dfs(i,j+1)
                    else:
                        nonlocal count
                        count += 1
            for i in range(row):
                for j in range(col):
                    dfs(i,j)
            return count
    class Solution:
        def countBattleships(self, board: List[List[str]]) -> int:
            count = 0
            row, col = len(board), len(board[0])
            for i in range(row):
                for j in range(col):
                    if board[i][j] == ".":
                        continue
                    if i>0 and board[i-1][j] == "X":
                        continue
                    if j>0 and board[i][j-1] == "X":
                        continue
                    count += 1
            return count

     

  • 相关阅读:
    好用的软件记录
    微信小程序 设计理念指南
    开启Python之路
    升级到iOS9之后的相关适配
    ARC模式下的内存泄露问题
    Git 源代码管理工具
    SVN版本控制系统
    单例 singleton
    双击改变图片大小和多点触摸改变图片大小
    循环引用 -- id 为什么是 assign 而不是 retain
  • 原文地址:https://www.cnblogs.com/mgdzy/p/13947599.html
Copyright © 2011-2022 走看看