23 - 合并K个升序链表
给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。
class Solution:
def merge2Lists(self, l1, l2):
'''
l1 and l2 are two linked lists
'''
head = ListNode()
rehead = head
while l1 and l2:
if l1.val < l2.val:
head.next = l1
l1 = l1.next
else:
head.next = l2
l2 = l2.next
head = head.next
if l1:
head.next = l1
else:
head.next = l2
return rehead.next
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
if not lists:
return None
else:
ans = lists.pop()
while lists:
ans = self.merge2Lists(ans, lists.pop())
return ans
先定义一个函数merge2Lists用于合并两个链表,然后对lists里的链表两两合并。
注意要考虑到lists为空的情况,此时应直接返回None
此题被标记为困难,通过单独定义一个函数可以分解问题,以后遇到复杂的问题可以考虑这一点。
26 - 删除排序数组中的重复项
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O ( 1 ) O(1) O(1) 额外空间的条件下完成。
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
mark = 0 #mark标记的是在弹出元素后当前指针的实际位置
for i in range(len(nums)):
if mark >= 1 and nums[mark] == nums[mark-1]:
nums.pop(mark)
mark -= 1
mark += 1
return mark
因为题目要求只使用 O(1) 额外空间,所以不可能维护一个要弹出元素下表的列表(要使用
O
(
n
)
O(n)
O(n)的额外空间)。那么自然想到使用指针。
定义一个指针mark,mark-1指向的是弹出元素后的列表的当前位置,也就是说,在每一次循环完成时,nums[:marker-1]都是无重复的有序列表。
索引i只是记录循环,没有别的作用,它保证了列表被完整的走完一次。
小细节:要返回的是列表nums的长度,本应是(mark-1)+1:
- mark-1是因为最后一次循环中的
mark += 1
已经超出了范围,所以要-1; - 再+1是因为mark是从0开始的,所以应该在索引基础上+1
33 - 搜索旋转排序数组
升序排列的整数数组 nums 在预先未知的某个点上进行了旋转(例如, [0,1,2,4,5,6,7] 经旋转后可能变为 [4,5,6,7,0,1,2] )。
请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
class Solution:
def search(self, nums: List[int], target: int) -> int:
if not nums:
return -1
l, r = 0, len(nums)-1
while l <= r:
#必须是<=,因为l=r=mid是一种重要的产生返回值的情况
mid = (l+r)//2
if nums[mid] == target:
return mid
if nums[l] <= nums[mid]:
#必须写成<=,因为l=mid时,[l,mid]只有一个值但也是有序的
if nums[l] <= target < nums[mid]:
#不能写成nums[l]<=target<=nums[mid-1],因为可能mid=l(==0)
r = mid - 1
else:
l = mid + 1
else:
if nums[mid] < target <= nums[r]:
l = mid + 1
else:
r = mid - 1
return -1
参考了官方解答
l和r指针维护的是当前判断的target的左右边界,mid是二分点。在每一次循环时,要分情况讨论,即判断[l,mid-1]和[mid+1,r]哪个才是有序的,对于旋转排序的数组,必然有一个是有序的。而结束的条件是nums[mid]=target,或者l>r还没有产生target.
这题的小细节不少,主要是判断条件的边界,可以自己画一画,以免出错。