笔记——week13_python

week13

知识点:

float('inf')

float('inf') 在 Python 中表示正无穷。它是一个特殊的值,比任何其他可能的数字都大。

原地算法:

原地算法是一种计算机算法,它只在输入数组上进行操作,而不是创建额外的存储空间。这可以节省内存和时间,尤其是在数组很大的情况下。

原地算法的一种常见用途是排序。例如,冒泡排序和插入排序都是原地算法。这些算法可以对数组中的元素进行排序,而无需创建额外的存储空间。

原地算法的另一种常见用途是搜索。例如,二分搜索是一种原地算法,它可以快速地在数组中查找指定的元素。

原地算法是计算机科学中重要的工具。它们可以用于解决各种各样的问题,包括排序、搜索和压缩。

zip() 函数:

在 Python 中,zip() 函数用于将两个或多个序列(列表、元组、字符串等)合并成一个元组列表。

例如,以下代码将两个列表合并成一个元组列表:

Python

list1 = [1, 2, 3]
list2 = [4, 5, 6]

result = list(zip(list1, list2))

print(result)

输出:

[(1, 4), (2, 5), (3, 6)]

zip() 函数的返回值是一个元组列表,其中每个元组包含来自两个原始序列的元素。在上面例子中,每个元组包含一个元素来自 list1 和一个元素来自 list2。

zip() 函数还可以用于将字符串合并成一个元组列表:

Python

str1 = "abc"
str2 = "def"

result = list(zip(str1, str2))

print(result)

输出:

[('a', 'd'), ('b', 'e'), ('c', 'f')]

zip() 函数是一个非常有用的函数,它可以用于将多个序列合并成一个元组列表。它可以用于解决各种各样的问题。

在 Python 中,zip() 函数用于将两个或多个序列(列表、元组、字符串等)合并成一个元组列表。

例如,以下代码将两个列表合并成一个元组列表:

Python

list1 = [1, 2, 3]
list2 = [4, 5, 6]

result = list(zip(list1, list2))

print(result)

输出:

[(1, 4), (2, 5), (3, 6)]

zip() 函数的返回值是一个元组列表,其中每个元组包含来自两个原始序列的元素。在上面例子中,每个元组包含一个元素来自 list1 和一个元素来自 list2。

zip() 函数还可以用于将字符串合并成一个元组列表:

Python

str1 = "abc"
str2 = "def"

result = list(zip(str1, str2))

print(result)

输出:

[('a', 'd'), ('b', 'e'), ('c', 'f')]

zip() 函数是一个非常有用的函数,它可以用于将多个序列合并成一个元组列表。它可以用于解决各种各样的问题。

简单:

448. 找到所有数组中消失的数字

题目描述

给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

示例 1:

输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]
code:
class Solution:
    def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
        seen = [False] * (len(nums) + 1)  # 记录出现的值
        result = []  # 记录结果
        for num in nums:  # 标记已出现的数值
            seen[num] = True

        for i in range(1, len(nums) + 1):  # [1, n]
            if seen[i] is False:  # 未出现的数值
                result.append(i)
        return result
class Solution:
    def find_disappeared_numbers(self, nums: List[int]) -> List[int]:
        """
        给定一个含 n 个整数的数组 nums ,找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

        时间复杂度:O(n)
        空间复杂度:O(1)

        Args:
            nums: 一个含 n 个整数的数组。

        Returns:
            一个包含所有没有出现过的数字的数组。
        """

        # 记录出现的值
        seen = [False] * (len(nums) + 1)

        # 记录结果
        result = []

        # 标记已出现的数值
        for num in nums:
            seen[num] = True

        # 遍历 [1, n],如果数值没有出现,则添加到结果数组中
        for i in range(1, len(nums) + 1):
            if seen[i] is False:
                result.append(i)

        return result
解题思路:

使用布尔数组 seen 来标记每个数字是否已经出现过。如果数字已经出现过,则将其标记为 True;如果数字没有出现过,则将其标记为 False。遍历完数组后,所有标记为 False 的数字就是所有没有出现过的数字。

  • seen 列表用于存储已经出现过的数字。
  • result 列表用于存储所有没有出现过的数字。
  • 循环遍历数组,如果数字已经出现过,则将其标记为已经出现过。
  • 遍历 [1, n],如果数值没有出现,则添加到 result 列表中。
  • 最后,返回 result 列表。

121. 买卖股票的最佳时机

题目描述:

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0

示例 1:

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
code:
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        min_price = float('inf')  # 初始最大价格保证最小的买入是在数组中
        max_profit = 0
        for price in prices:
            min_price = min(price, min_price)  # 得到数组最小买入
            max_profit = max(max_profit, price - min_price)  # 更新最大利润
        return max_profit
解题思路:

贪心算法:因为只用一买一出,所以要计算最小的price和最大的price的价格,该算法的好处就像等于将 [ 1 , 2 , 3 , 2 , 6 , 7 ] ⟶ [ [ 1 , 3 ] , [ 2 , 7 ] ] ⟶ [ 2 , 5 ] [1,2,3,2,6,7]\longrightarrow[[1,3],[2,7]]\longrightarrow[2,5] [1,2,3,2,6,7][[1,3],[2,7]][2,5]我们要的结果就是5。

118. 杨辉三角

题目描述:

给定一个非负整数 *numRows,*生成「杨辉三角」的前 numRows 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

img

示例 1:

输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]
code:
class Solution:
    def generate(self, num_rows: int) -> List[List[int]]:
        # 初始化结果列表。
        result = []
        for row in range(num_rows):
            # 初始化当前行的列表。
            row_list = []
            for col in range(row + 1):
                # 如果当前列为 0 或行数,则元素为 1。
                if col == 0 or col == row:
                    row_list.append(1)
                # 否则,元素为上两元素之和。
                else:
                    row_list.append(result[row - 1][col - 1] + result[row - 1][col])
            # 添加当前行的列表到结果列表。
            result.append(row_list)

        return result
解题思路:

简单的动态规划,处理每行的结果,在逐一添加答案。

中等:

442. 数组中重复的数据

题目描述:

给你一个长度为 n 的整数数组 nums ,其中 nums 的所有整数都在范围 [1, n] 内,且每个整数出现 一次两次 。请你找出所有出现 两次 的整数,并以数组形式返回。

你必须设计并实现一个时间复杂度为 O(n) 且仅使用常量额外空间的算法解决此问题。

示例 1:

输入:nums = [4,3,2,7,8,2,3,1]
输出:[2,3]
code:
class Solution:
    def findDuplicates(self, nums: List[int]) -> List[int]:
        seen = [False] *(len(nums) + 1)  # 构建hash表
        result = []  # 结果记录
        for num in nums:
            if seen[num]:  # 第二次出现
                result.append(num)
            else:  # 第一次出现
                seen[num] =  True
        return result
class Solution:
    def findDuplicates(self, nums: List[int]) -> List[int]:
        """
        给定一个长度为 n 的整数数组 nums ,找出所有出现 两次 的整数,并以数组形式返回。

        时间复杂度:O(n)
        空间复杂度:O(1)

        Args:
            nums: 一个长度为 n 的整数数组。

        Returns:
            一个包含所有出现 两次 的整数的数组。
        """

        # 构建哈希表
        seen = [False] * (len(nums) + 1)

        # 结果记录
        result = []

        # 遍历数组
        for num in nums:
            # 如果数字已经出现过
            if seen[num]:
                # 将其添加到结果数组中
                result.append(num)
            # 否则
            else:
                # 将其标记为已经出现过
                seen[num] = True

        # 返回结果数组
        return result
解题思路:
  • seen 列表用于存储已经出现过的数字。
  • result 列表用于存储所有出现过两次的数字。
  • 循环遍历数组,如果数字已经出现过,则将其添加到 result 列表中,否则将其标记为已经出现过。
  • 最后,返回 result 列表。

原地hsah表,因为条件限制所以,难度大大下降

  • n == nums.length
  • 1 <= n <= 105
  • 1 <= nums[i] <= n
  • nums 中的每个元素出现 一次两次

55. 跳跃游戏

题目描述:

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

示例 1:

输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
code:
class Solution:
    def canJump(self, nums: List[int]) -> bool:
        n = len(nums)
        max_right = 0
        for i in range(n):
            # 如果当前位置可以达到
            if i <= max_right:
                # 更新可以达到的最大位置
                max_right = max(max_right, i + nums[i])
                # 如果可以达到数组的最后一个位置
                if max_right >= n - 1:
                    return True
        return False
解题思路:

贪心算法:在不超过最大界限的范围内,可以达到的最大位置,若超过最大的右边界,则可以跳跃到最后一个下标。

73. 矩阵置零

题目描述:

给定一个 *m* x *n* 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法**。**

示例 1:

img

输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]
code:
class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        """
        `m` 和 `n` 分别是矩阵的行数和列数。
        `row_has_zero` 是一个布尔列表,表示矩阵中的每一行是否包含 0 元素。
        `col_has_zero` 是一个布尔列表,表示矩阵中的每一列是否包含 0 元素。
        """
        m, n = len(matrix), len(matrix[0])
        row_has_zero = [False] * m
        col_has_zero = [False] * n

        """
        遍历矩阵,并将所有包含 0 元素的行和列的元素置为 0。
        """
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0:
                    row_has_zero[i] = True
                    col_has_zero[j] = True

        """
        遍历矩阵,并将所有被标记为 0 的行和列的元素置为 0。
        """
        for i in range(m):
            for j in range(n):
                if row_has_zero[i] or col_has_zero[j]:
                    matrix[i][j] = 0
解题思路:

首先创建两个布尔数组,分别表示矩阵中的行和列是否包含 0 元素。然后,遍历矩阵,并将所有包含 0 元素的行和列的元素置为 0。最后,返回修改后的矩阵。

54. 螺旋矩阵

题目描述:

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

示例 1:

img

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
code:
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        # 初始位置和界限
        row_start = 0
        row_end = len(matrix) - 1
        col_start = 0
        col_end = len(matrix[0]) - 1
        result = []

        # 开始循环
        while row_start <= row_end and col_start <= col_end:
            # 正向行
            for col in range(col_start, col_end + 1):
                result.append(matrix[row_start][col])

            # 到下一行
            row_start += 1

            # 正向列
            for row in range(row_start, row_end + 1):
                result.append(matrix[row][col_end])

            # 到下一列
            col_end -= 1

            # 反向行
            if row_start <= row_end:
                for col in range(col_end, col_start - 1, -1):
                    result.append(matrix[row_end][col])

                row_end -= 1

            # 反向列
            if col_start <= col_end:
                for row in range(row_end, row_start - 1, -1):
                    result.append(matrix[row][col_start])

                col_start += 1

        return result

解题思路:

模拟算法,模拟数值的添加路线,要注意range的集合是一个左闭右开的区间。

79. 单词搜索

题目描述:

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例 1:

img

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
code:
class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        m, n = len(board), len(board[0])
        for i in range(m):
            for j in range(n):
                if self.dfs(board, word, i, j, m, n):
                    return True
        return False

    def dfs(self, board, word, i, j, m, n):
        if i < 0 or i >= m or j < 0 or j >= n or board[i][j] != word[0]:
            return False
        if len(word) == 1:
            return True
        board[i][j] = '#'
        for choice in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            if self.dfs(board, word[1:], i + choice[0], j + choice[1], m, n):
                return True
        board[i][j] = word[0]
        return False
解题思路;

逐个字母地比较单词。如果两个字母匹配,则会向右或向下移动一个单元格,并继续比较下一个字母。如果两个字母不匹配,或者到达了网格的边界,则算法会返回 False。

小细节在 dfs 函数中,board[i][j] = '#' 语句将 # 标记符赋值给二维列表 boardi 行和 j 列中的元素。这是为了防止单词被多次找到。

48. 旋转图像

题目描述:

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在** 原地** 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例 1:

img

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]
code:
class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        n = len(matrix)  # 矩阵的维度
        for i in range(n // 2):  # 遍历上半部分行
            for j in range((n + 1) // 2):  # 遍历上半部分列
                # 进行四个元素的位置交换
                matrix[i][j], matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1] = matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1], matrix[i][j]
解题思路:

可以观察到,旋转前后,原矩阵左上角的元素,会移动到右上角的位置,右上角的元素会移动到右下角的位置,右下角的元素会移动到左下角的位置,左下角的元素会移动到左上角的位置。因此,我们可以通过对矩阵中的四个元素进行位置交换来实现矩阵的旋转。

具体地,我们从外部的一圈元素开始,每次遍历对应一圈的四个边,对四个边的元素进行位置交换。遍历的终止条件是遍历完所有的圈。

需要注意的是,当矩阵的维度为奇数时,最中间的一行和一列只包含一个元素,不需要进行位置交换。

这样,就能够实现将矩阵顺时针旋转90度的操作。

困难:

41. 缺失的第一个正数

题目描述:

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

示例 1:

输入:nums = [1,2,0]
输出:3
code:
class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        n = len(nums)  # 获取数组的长度
        for i in range(n):
            if nums[i] <= 0:  # 处理非正整数
                nums[i] = n + 1
        for i in range(n):
            num = abs(nums[i])
            if num <= n:  # 处理(1, N)的数
                nums[num - 1] = -abs(nums[num - 1])  # 这里开始使用的是一个简单的负数值,没有考虑到重复的数
        for i in range(n):  # 开始扫描
            if nums[i] > 0:
                return i + 1  
        return n + 1=
解题思路:

对于一个长度为N的数组,其中没有出现的的最小正整数只能在 [ 1 , N + 1 ] [1, N + 1] [1,N+1]。如果 [ 1 , N ] [1, N] [1,N]都出现了,那么答案就是 N + 1 N+1 N+1,否则就是 [ 1 , N ] [1, N] [1,N]中没有出现的最小正整数。

其他

ass Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
n = len(nums) # 获取数组的长度
for i in range(n):
if nums[i] <= 0: # 处理非正整数
nums[i] = n + 1
for i in range(n):
num = abs(nums[i])
if num <= n: # 处理(1, N)的数
nums[num - 1] = -abs(nums[num - 1]) # 这里开始使用的是一个简单的负数值,没有考虑到重复的数
for i in range(n): # 开始扫描
if nums[i] > 0:
return i + 1
return n + 1(=


#### 解题思路:

对于一个长度为N的数组,其中没有出现的的最小正整数只能在$[1, N + 1]$。如果$[1, N]$都出现了,那么答案就是$N+1$,否则就是$[1, N]$中没有出现的最小正整数。















## 其他



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值