数组
二分查找(704)
二分法详细思路和理解参考我前一篇代码随想录的帖子
函数定义
1.def search(self, nums: List[int], target: int) -> int:是什么意思?
这是一个方法的定义,用于在一个整数列表中搜索目标值。让我们逐部分解释:
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 中,除法运算符有两种:
-
浮点除法 (
/
):- 使用单个斜杠
/
进行除法运算,结果总是浮点数,即使两个操作数都是整数。 - 例如:
5 / 2
的结果是2.5
。
- 使用单个斜杠
-
整数除法 (
//
):- 使用双斜杠
//
进行除法运算,结果是向下取整的整数(即截断小数部分)。 - 例如:
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]**2
或nums[left] * nums[left]
,因为^
是按位异或运算符,而不是乘方运算符。left++
和right--
语法错误,应该分别是left += 1
和right -= 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: ListNode
:head
是方法的第一个参数,表示链表的头节点。ListNode
是链表节点的类型注解,表明head
应该是一个ListNode
对象。 -
val: int
:val
是方法的第二个参数,表示要从链表中移除的值。类型注解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 允许你在构造函数中同时设置 val
和 next
。这使得代码更加简洁。