1、有序链表合并
1.1 两个有序链表合并
题目描述
给出两个有序的整数数组A和B,请将数组 B合并到数组A中,变成一个有序的数组
注意:
可以假设A数组有足够的空间存放B数组的元素,A和B中初始的元素数目分别为m和n
- 解题思路
一般有递归与迭代两种方法,迭代方法后续补充
方法一:递归
如果left或者right一开始就是空链表,那么没有任何操作需要合并,所以我们只需要返回非空链表。
否则,我们要判断left 和right 哪个链表的头节点的值更小,然后递归地决定下一个添加到结果里的节点,如果两个链表都为空,递归结束。
- 复杂度分析
时间复杂度:
O(n + m), 其中n, m分别为两个链表的长度。因为每次调用递归都会去掉left, right的头节点(直到其中一个为空),函数merge至多只会调用每个节点一次。因此,时间复杂度取决于合并后的链表的长度,即O(n + m)。
空间复杂度:
O(n + m),其中n, m分别为两个链表的长度。递归调用merge函数时,需要耗费栈空间,栈空间的大小取决于递归调用的深度。结束递归调用时merge函数最多调用 n + m 次, 所以空间复杂度为O(n + m)
- 代码实现
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoList(self, left, right):
if left is None: return right
if right is None: return left
if left.val < right.val:
left.next = self.mergeTwoList(left.next, right)
return left
else:
right.next = self.mergeTwoList(left, right.next)
return right
1.2 对K个有序链表合并
题目描述
合并 k 个已排序的链表并将其作为一个已排序的链表返回。分析并描述其复杂度。
示例1
输入
[{1,2,3},{4,5,6,7}]
返回值
{1,2,3,4,5,6,7}
- 解题思路
采用分治法来合并有序链表
- 代码实现
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
if len(lists) == 0 :
return
head = None
for list_ in lists:
head = self.mergeTwoList(head, list_)
return head
def mergeTwoList(self, left, right):
if left is None: return right
if right is None: return left
if left.val < right.val:
left.next = self.mergeTwoList(left.next, right)
return left
else:
right.next = self.mergeTwoList(left, right.next)
return right
2、判断链表是否存在环
hash map 与快慢指针
- 解题思路
方法一:快慢指针,如果慢指针能追上快指针说明存在环
用一快一慢指针,开始两个指针都指向链表头部。慢指针每次向前走一步,快指针每次向前走两步。如果有环,则两个指针最终一定会相遇。这种方法无须额外的空间。
- 代码实现
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
#
# @param head ListNode类
# @return bool布尔型
#
class Solution:
def hasCycle(self , head ):
# write code here
if head is None or head.next is None:
return False
fast = head
slow = head
while (fast is not None) and (fast.next is not None):
fast = fast.next.next
slow = slow.next
if fast == slow:
return True
return False
3、删除链表中一个元素
题目描述
给定一个链表,删除链表的倒数第n个节点并返回链表的头指针
例如,
给出的链表为:1->2->3->4->5, n= 2.
删除了链表的倒数第n个节点之后,链表变为1->2->3->5.
备注:
题目保证n一定是有效的
请给出请给出时间复杂度为\ O(n) O(n)的算法
- 解题思路:
基本思路双指针,问题的关键在于找到倒数第N个节点,并且尽量只使用一次循环。
采用双指针,对前指针,使其先走出N步,随后两指针同时前进,当前指针达到链表尾部时, 后指针到达倒数第N个节点的位置。
- 代码实现:
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
#
# @param head ListNode类
# @param n int整型
# @return ListNode类
#
class Solution:
def removeNthFromEnd(self , head , n ):
# write code here
if head is None and head.next is None:
return head
dummy = ListNode(0)
dummy.next = head
head = dummy
fast = head
slow = head
for _ in range(n):
fast = fast.next
while fast.next:
slow = slow.next
fast = fast.next
temp = slow.next
slow.next = slow.next.next
return dummy.next