《代码随想录》学习笔记,原链接:https://programmercarl.com/
27.移除元素
(1)题目分析
数组删除某个元素,并不是直接删除,而是后面的元素前移来覆盖掉删除位置的元素。因此,删除前后数组所占的内存大小是不变的。
如上图所示,原数组size为8,删除元素2后size变为6,而最后两个元素未处理,即后面两个位置的元素是什么无所谓。但需要注意的是,删除后数组的内存大小依然为8,只是有的编程语言会对数组进行包装,在erase()删除元素后,计数器会自动执行- 1操作,使得数组的size - 1。
【注】erase()函数用于删除数组中的某一个元素,时间复杂度为O(n),而不是O(1)。
(2)双指针法
双指针法(快慢指针法):通过一个快指针和慢指针,在一个for循环下完成两个for循环的工作。
- 快指针:获取新数组的元素。
- 慢指针:获取新数组中需要更新的位置下标。
(3)双指针法代码
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
# 双指针法
slow, fast = 0, 0
while fast < len(nums): # 不加等于是因为,fast = len(nums)时,nums[fast] 会越界
if nums[fast] != val:
nums[slow] = nums[fast] # slow用来收集不等于val的值,如果fast对应值不等于val,则把它赋值给nums[slow]
slow += 1
fast += 1
return slow
【注】range()函数是左包含、右不包含,即range(2)只能取到0和1两个值。
(4)ACM模式
class Solution:
def removeElement(self, nums, val):
# 双指针法
slow, fast = 0, 0
while fast < len(nums): # 不加等于是因为,fast = len(nums)时,nums[fast] 会越界
if nums[fast] != val:
nums[slow] = nums[fast] # slow用来收集不等于val的值,如果fast对应值不等于val,则把它赋值给nums[slow]
slow += 1
fast += 1
return slow
# 自定义数据列表和要删除的元素值
nums = list(map(int, input("输入整数数组:").split(",")))
val = int(input("输入要删除的元素:"))
# 移除元素
solution = Solution()
result = solution.removeElement(nums, val)
print(result)
【注】list(map(int, input("输入已排序的整数数组:").split(","))),分析:
- input() 函数:用于从用户输入获取一个由逗号分隔的整数组成的字符串。
- split() 方法:用于将输入的字符串按照逗号分隔成多个子字符串,并返回子字符串构成的列表。如输入1,2,3时,将返回['1', '2', '3']。
- map() 函数:用于对子字符串列表中的每个元素应用指定的函数。具体来说,map() 函数接收两个参数,第一个参数是一个函数,第二个参数是一个可迭代对象,它将该函数依次作用于可迭代对象中的每个元素,并返回一个由结果组成的新的可迭代对象。例如map(int, ['1', '2', '3']) ,会将字符串列表中的每个元素转换为整数类型,并返回一个由整数组成的新的可迭代对象 [1][2][3]。
- int() 函数:用于将字符串转换为整数类型的函数。
- list() 函数:用于将可迭代对象 [1][2][3]转换为列表类型[1, 2, 3],从而得到用户输入的整数列表。
移除元素相关题目
(1)26.删除有序数组中的重复项
- 核心代码模式
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
slow = fast = 0
while fast < len(nums):
if nums[fast] != nums[slow]:
slow += 1
nums[slow] = nums[fast]
fast += 1
return slow + 1
- ACM模式
class Solution:
def removeDuplicates(self, nums):
slow = fast = 0
while fast < len(nums):
if nums[fast] != nums[slow]:
slow += 1
nums[slow] = nums[fast]
fast += 1
return slow + 1
# 自定义数据列表
nums = list(map(int, input("输入整数数组:").split(",")))
# 删除有序数组中的重复项
solution = Solution()
result = solution.removeDuplicates(nums)
print(result)
(2)283.移动零
- 核心代码模式
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
slow = fast = 0
while fast < len(nums):
if nums[fast] != 0:
nums[slow] = nums[fast]
slow += 1
fast += 1
for i in range(len(nums[slow: ])): # slow等于数组中非0元素的个数
nums[slow + i] = 0 # 数组末尾元素全部置0
【注】 for i in range(len(nums[slow: ])):中,slow表示数组中非0元素的个数。以nums = [0,1,0,3,12]为例,在while循环结束后slow = 3。
- 由于a: b表示左闭右开区间[a, b)的整数切片,而当b省略时默认表示列表的lenth,所以len(nums[slow: ]) = len(nums[3: 5]) = len(nums[3, 4]) = 2。
- 由于range()函数也是左包含、右不包含,因此range(len(nums[slow: ]) = range(2) = 0, 1两个值。
- ACM模式
class Solution:
def moveZeroes(self, nums):
"""
Do not return anything, modify nums in-place instead.
"""
slow = fast = 0
while fast < len(nums):
if nums[fast] != 0:
nums[slow] = nums[fast]
slow += 1
fast += 1
for i in range(len(nums[slow:])): # slow等于数组中非0元素的个数
nums[slow + i] = 0 # 数组末尾元素全部置0
return nums
# 自定义数据列表
nums = list(map(int, input("输入整数数组:").split(",")))
# 删除数组中的0
solution = Solution()
result = solution.moveZeroes(nums)
print(result)
(3)844.比较含退格的字符串
- 核心代码模式
class Solution:
def backspaceCompare(self, s: str, t: str) -> bool:
def stringProcess(string):
slow = 0 # 构建双指针
stringList = list(string) # 字符串不可修改,先转换成列表
for fast in range(0, len(stringList)): # 循环遍历字符串列表
if stringList[fast] == '#': # 如果当前为退格符
slow -= 1
if slow < 0: # 防止超出列表范围
slow = 0
else:
stringList[slow] = stringList[fast] # 更新原字符串列表
slow += 1
newString = "".join(stringList[:slow]) # 生成退格之后的字符串
return newString
# 对含有退格的字符串进行处理
sNew = stringProcess(s)
tNew = stringProcess(t)
return sNew == tNew # 返回两个处理后的字符串是否相等的判断结果
【注】关于字符串的修改和合并:
- ACM模式
class Solution:
def backspaceCompare(self, s, t):
def stringProcess(string):
slow = 0 # 构建双指针
stringList = list(string) # 字符串不可修改,先转换成列表
for fast in range(0, len(stringList)): # 循环遍历字符串列表
if stringList[fast] == '#': # 如果当前为退格符
slow -= 1
if slow < 0: # 防止超出列表范围
slow = 0
else:
stringList[slow] = stringList[fast] # 更新原字符串列表
slow += 1
newString = "".join(stringList[:slow]) # 生成退格之后的字符串
return newString
# 对含有退格的字符串进行处理
sNew = stringProcess(s)
print(sNew)
tNew = stringProcess(t)
print(tNew)
return sNew == tNew # 返回两个处理后的字符串是否相等的判断结果
# 输入待比较的两个字符串
s = input('输入字符串s:')
t = input('输入字符串t:')
# 比较含退格的字符串
solution = Solution()
result = solution.backspaceCompare(s, t)
print(result)
(4)977.有序数组的平方
- 核心代码模式
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
result = [float("inf")] * len(nums) # 初始化存放平方结果的列表
i, j, k = 0, len(nums) - 1, len(nums) - 1
while i <= j: # 从两边到中间,平方值从大到小倒序存放在result中
if nums[i] ** 2 < nums[j] ** 2:
result[k] = nums[j] ** 2
j -= 1
else:
result[k] = nums[i] ** 2
i += 1
k -= 1
return result
【注】result = [float("inf")] * len(nums),初始化result列表,其中float("inf")表示每个元素初始化为﹢∞,len(nums)表示初始化列表的长度。由于之后会有通过下标访问列表中元素的操作result[k],因此不能单纯result = [],需要提前初始化列表的长度。
- ACM模式
class Solution:
def sortedSquares(self, nums):
result = [float("inf")] * len(nums) # 初始化存放平方结果的列表
i, j, k = 0, len(nums) - 1, len(nums) - 1
while i <= j: # 从两边到中间,平方值从大到小倒序存放在result中
if nums[i] ** 2 < nums[j] ** 2:
result[k] = nums[j] ** 2
j -= 1
else:
result[k] = nums[i] ** 2
i += 1
k -= 1
return result
# 自定义数据列表
nums = list(map(int, input("输入要进行平方的列表:").split(",")))
# 有序数组的平方
solution = Solution()
result = solution.sortedSquares(nums)
print(result)
(5)88.合并两个有序数组
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
i, j, k = m - 1, n - 1, m + n - 1
while i >= 0 and j >= 0: # 将合并结果倒序存放到nums1中
if nums1[i] < nums2[j]:
nums1[k] = nums2[j]
j -= 1
else:
nums1[k] = nums1[i]
i -= 1
k -= 1
if i == -1: # 如果nums1中的元素已经全部被访问,则将nums2中的剩余元素直接按照原排序存放
while k >= 0:
nums1[k] = nums2[j]
j -= 1
k -= 1
【注】语法a:b,表示从索引a到索引b(不包含b),如果省略a则默认为0,如果省略b则默认为序列的长度(如len(nums2)。如crop[:2],表示取crop[0]和crop[1]两个元素,并不包含crop[2]。