纯小白自学代码随想录(Python刷题版)笔记 (每日一题)

数组

二分查找(704)

二分法详细思路和理解参考我前一篇代码随想录的帖子

函数定义

1.def search(self, nums: List[int], target: int) -> int:是什么意思?

这是一个方法的定义,用于在一个整数列表中搜索目标值。让我们逐部分解释:

  1. def search(self, nums: List[int], target: int) -> int:
    • def 是定义函数的关键字。
    • search 是函数的名称。
    • self 是指代类实例的惯用参数,在定义类的方法时必须包含。
    • nums: List[int] 表示 nums 是一个包含整数的列表。
    • target: int 表示 target 是一个整数。
    • -> int 表示这个函数返回一个整数类型的值。

整体来看,这个方法是在一个类中定义的,用于在 nums 列表中搜索 target 值,返回值是一个整数。

2.List 不是自己定义的名称,它是 Python 的标准库 typing 模块中的一个类型注解。List 用于指定函数参数或返回值的类型,以便提高代码的可读性和可维护性。要使用 List,你需要在代码的开头导入它:

from typing import List

这样,List[int] 就表示一个整数列表。完整的示例代码可能是这样的:

from typing import List

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        # 方法实现部分
        pass

在这个示例中,search 方法的 nums 参数是一个由整数组成的列表,target 是要查找的整数,方法返回一个整数。List 提供了更明确的类型信息。

除号

3.在 Python 中,除法运算符有两种:

  1. 浮点除法 (/):

    • 使用单个斜杠 / 进行除法运算,结果总是浮点数,即使两个操作数都是整数。
    • 例如:5 / 2 的结果是 2.5
  2. 整数除法 (//):

    • 使用双斜杠 // 进行除法运算,结果是向下取整的整数(即截断小数部分)。
    • 例如:5 // 2 的结果是 2

在二分查找算法中,为了确保索引是整数,我们通常使用整数除法 //。例如:

middle = (left + right) // 2

这确保了 middle 始终是一个整数,这在数组索引中是必需的。

总结一下:

  • 使用 / 进行浮点除法。
  • 使用 // 进行整数除法。

代码:


# (版本一)左闭右闭区间
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left, right = 0, len(nums) - 1
        
        while left <= right:
            middle = (left + right) // 2

            if nums[middle] < target:
                left = middle + 1
            elif nums[middle] > target:
                right = middle - 1
            else:
                return middle
        return -1

# (版本二)左闭右开区间

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left,right  =0, len(nums)
        while left < right:
            mid = (left + right) // 2
            if nums[mid] < target:
                left = mid+1
            elif nums[mid] > target:
                right = mid
            else:
                return mid
        return -1

移除元素(27)

快指针用来获取数组的元素,慢指针获取新数组中需要更新的位置

我根据代码随想录讲的快慢指针写的:

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        fast = 0
        slow = 0
        while fast < len(nums):
            if nums[fast]!=val:
                nums[slow]=nums[fast]
                slow = slow+1
            fast = fast+1
        return slow

注意fast和slow分两行定义,写在一行会报错。

有序数组的平方(977)

双指针,从左右两边往中间遍历

我写的错误代码及解释:

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        left=0
        right=len(nums)-1
        k=len(nums)-1
        for left<=right:
            if nums[left]^2>nums[right]^2:
                result[k]=nums[left]
                left++
            elif:
                result[k]=nums[right]
                right--
        return result

解释:

  • 语法错误

    • for left<=right: 应该是 while left <= right:
    • nums[left]^2 应该是 nums[left]**2nums[left] * nums[left],因为 ^ 是按位异或运算符,而不是乘方运算符。
    • left++right-- 语法错误,应该分别是 left += 1right -= 1
    • elif: 需要条件,应该是 else:
  • 初始化 result 数组

    • 需要在开始时初始化 result 数组,其长度与 nums 相同。

for循环的用法:

for i in range(len(nums)):
    # 执行你的操作
    print(nums[i])

正确代码:

from typing import List

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        left = 0
        right = len(nums) - 1
        k = len(nums) - 1
        result = [0] * len(nums)
        
        while left <= right:
            if nums[left] ** 2 > nums[right] ** 2:
                result[k] = nums[left] ** 2
                left += 1
            else:
                result[k] = nums[right] ** 2
                right -= 1
            k -= 1
        
        return result

长度最小的子数组(209)

双指针,每次循环定下子数组的右边界,动左边界

from typing import List

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        current_sum = 0
        i = 0
        min_length = float('inf')
        
        for j in range(len(nums)):
            current_sum += nums[j]
            
            while current_sum >= target:
                min_length = min(min_length, j - i + 1)
                current_sum -= nums[i]
                i += 1
        
        return 0 if min_length == float('inf') else min_length

易错点:初始化时用min_length = float('inf')。i+=1要在计算min_length后面,否则影响min_length计算。

螺旋矩阵(59)

1.初始化矩阵

mat = [[0 for _ in range(n)] for _ in range(n)]

这行代码用于创建一个 n x n 的二维矩阵(列表的列表),其中所有元素都初始化为 0。下面是对这行代码的详细解释:

  • 内层列表推导式[0 for _ in range(n)]

    这部分代码创建一个长度为 n 的列表,其中所有元素都初始化为 0。使用了列表推导式的语法。这里的 for _ in range(n) 表示循环 n 次,并且每次循环时都添加一个 0 到列表中。_ 是一个惯例用法,用于表示我们不关心循环变量的值。

  • 外层列表推导式[[0 for _ in range(n)] for _ in range(n)]

    这部分代码创建一个包含 n 个内层列表的外层列表。每个内层列表都是通过前面的内层列表推导式生成的。因此,它创建了一个 n x n 的矩阵,其中所有元素都初始化为 0

n = 5
one_d_list = [0 for _ in range(n)]  # 一维列表
two_d_matrix = [[0 for _ in range(n)] for _ in range(n)]  # 二维矩阵

2.矩阵索引是mat[x+i][n-1-(r-1)],而不是用圆括号索引

3.    def generateMatrix(self, n: int) -> List[List[int]]:

  • def 关键字用于定义一个方法。
  • generateMatrix 是方法的名称。
  • self 表示这是一个类的方法,self 引用了该类的实例。
  • n: int 表示参数 n 是一个整数类型。这是 Python 的类型注解,提示 n 应该是一个整数。
  • -> List[List[int]] 是方法的返回类型注解,表示该方法返回一个二维列表(列表的列表),其中每个元素都是整数。

根据代码随想录思想写的代码:

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        mat=[[0 for _ in range(n)] for _ in range(n)]
        x=0
        y=0
        offset = 0
        r=1
        num = 1
        while r<=n/2:
            for i in range(n-offset-1):
                mat[x][y+i]=num
                num+=1
            for i in range(n-offset-1):
                mat[x+i][n-1-(r-1)]=num
                num+=1
            for i in range(n-offset-1):
                mat[n-1-(r-1)][n-1-(r-1)-i]=num
                num+=1
            for i in range(n-offset-1):
                mat[n-1-(r-1)-i][y]=num
                num+=1
            r+=1
            offset+=2
            x+=1
            y+=1
        if n%2!=0:
            mat[floor(n/2)][floor(n/2)]=num
        return mat

链表

移除链表元素(203)

如果使用C,C++编程语言的话,不要忘了还要从内存中删除这两个移除的节点,当然如果使用java ,python的话就不用手动管理内存了。

代码:

# Definition for singly-linked list.

# class ListNode:

#     def __init__(self, val=0, next=None):

#         self.val = val

#         self.next = next

class Solution:

    def removeElements(self, head: ListNode, val: int) -> ListNode:

        dummy_head = ListNode(next=head) #添加一个虚拟节点

        cur = dummy_head

        while(cur.next!=None):

            if(cur.next.val == val):

                cur.next = cur.next.next #删除cur.next节点

            else:

                cur = cur.next

        return dummy_head.next

解释:

1.def removeElements(self, head: ListNode, val: int) -> ListNode:这行代码定义了一个方法 removeElements,它是用于从链表中移除指定值的节点,并返回处理后的链表的头节点。下面是对这行代码的详细解释:

1. 方法定义

  • def:这是定义函数或方法的关键字。

  • removeElements:这是方法的名称。通常,这个方法名应该表达其功能——在这里是移除链表中的指定元素。

2. 参数

  • self:这是一个典型的 Python 类方法的第一个参数,它代表类的实例。在类的方法中,self 用来访问类的属性和其他方法。

  • head: ListNodehead 是方法的第一个参数,表示链表的头节点。ListNode 是链表节点的类型注解,表明 head 应该是一个 ListNode 对象。

  • val: intval 是方法的第二个参数,表示要从链表中移除的值。类型注解 int 表示 val 应该是一个整数。

3. 返回类型

  • -> ListNode:这部分表示该方法的返回类型为 ListNode,即处理后的链表头节点。

2.dummy_head = ListNode(next=head) #添加一个虚拟节点

1. 创建虚拟节点

  • ListNode(next=head) 创建了一个新的 ListNode 对象。

  • next=head 表示这个新节点的 next 指针指向原链表的头节点 head

2. 作用

  • 简化操作:在链表操作中,处理第一个节点往往需要特殊处理(例如删除头节点),引入虚拟节点可以统一处理链表的所有节点,避免对头节点的特殊判断。

  • 保持链表结构:虚拟节点作为链表的第一个节点,但它通常不会包含有效数据,最终返回时也会跳过它。

注:

1.ListNode只是一个节点,不是一整个链表!

2.chatgpt的评价是最好这样初始化头结点:

dummy_head = ListNode(0) # 初始化虚拟头节点,值为0 dummy_head.next = head # 虚拟头节点指向真正的头节点

完整代码:

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        dummy_head = ListNode(0)  # 初始化虚拟头节点,值为0
        dummy_head.next = head  # 虚拟头节点指向真正的头节点
        cur = dummy_head  # 初始化当前节点指针

        while cur.next is not None:
            if cur.next.val == val:
                cur.next = cur.next.next  # 删除cur.next节点
            else:
                cur = cur.next  # 移动指针

        return dummy_head.next  # 返回真正的头节点

3.也可以这样初始化:
dummy_head = ListNode(0, head)

这行代码与之前的 dummy_head = ListNode(next=head) 是等价的,只不过这里显式地为虚拟节点的 val 赋值为 0,而且 Python 允许你在构造函数中同时设置 valnext。这使得代码更加简洁。

设计链表(707)

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当你作为一个小白自学Python时,以下是一些建议和步骤: 1. 学习编程基础知识:在开始学习Python之前,了解一些基本的编程概念和术语是很重要的。你可以学习一些基本的计算机科学概念,如变量、数据类型、条件语句、循环等。 2. 学习Python语法:Python是一种易于学习和理解的编程语言。你可以通过在线教程、视频教程或参考书籍来学习Python的语法规则和基本语句。掌握Python的基本语法是你进一步学习和开发的基础。 3. 练习编写代码:通过实践来巩固所学的知识是非常重要的。尝试编写一些简单的程序来解决问题,例如计算器、猜数字游戏等。这样可以帮助你熟悉Python的语法和逻辑。 4. 使用在线资源:互联网上有很多免费的资源可以帮助你学习Python。你可以参考一些优质的网站、博客、论坛和社区,如CSDN、Stack Overflow等。这些资源提供了大量的教程、示例代码和解答问题的平台。 5. 参与项目或实践:参与一些开源项目或实践项目可以帮助你更好地理解和应用Python。你可以加入一些开源社区,与其他开发者合作,共同开发项目。这样可以提高你的编程技能和经验。 6. 持续学习和提升:编程是一个不断学习和提升的过程。随着你的学习和实践,你会遇到更多的问题和挑战。不断学习新的知识,探索更深入的主题,参与更复杂的项目,可以帮助你不断提升自己的编程能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值