LeetCode 206 反转链表的理解与分析 Python3

原题链接:LeetCode 206 反转链表

反转一个单链表。
LeetCode 206 反转链表的理解与分析 Python3_第1张图片
就直接按照进阶的要求自己吧。

解法一

迭代法+双指针

def reverseList(head):
     if not head:
         return None
     pre, cur = head, head.next
     while cur:
         # temp 为临时变量 用于保存下一个cur需要更新的节点
         temp = cur.next
         cur.next = pre
         pre = cur
         cur = temp
     head.next = None
     return pre

在评论区看到一个有意思的写法,只是较为巧妙地利用了python的赋值语句,举例说明一下:如果原链表为1->2->3->4->None,很明显,等号右边为(1, None, 2),依次执行赋值:rev = 1,反转:rev.next = rev,此时就变为1->None,赋值:p = p.next,此时p指向的是2,需要注意的是由于并行赋值的原因,p节点未受到影响,这里2->3->4->None依然存在。然后就依次迭代进行,直到p节点为空:

def reverseList(head):
	p, rev = head, None
	while p:
		# 这是一种并行赋值
		# 等号右边会被当做一个元组(tuple)打包 
		# 然后解包(unpack)给等号右边
		rev, rev.next, p = p, rev, p.next
	return rev

解法二

递归法
递归相对而言不好理解的就是,我们在递归原链表时,应当返回递归最深处,也就是最后一个节点作为反转链表的头。这也就决定了该节点需要一直往上回溯到程序结束的地方。相应的,递归程序的主体部分就是用来反转两个节点。需要注意的是,我们返回的结果需要保证原链表的head节点的next应为None,对此,也在递归主体部分完成。说起来相对比较绕,看看程序,画画图应该能大体理解。

def reverseList(head):
	# 递归结束 返回最后一个节点作为结果的头节点
	if not head or not head.next:
		return head
	node = reverseList(head.next)
	# 反转
	head.next.next = head
	# 处理None
	head.next = None
	return node 

设n为节点个数。两种解法的时间复杂度都为O(n),因为都仅仅遍历了所有的节点一次。而迭代法只用到了常数级别的空间复杂度,递归的空间复杂度为O(n)。

note:
几个月前,自己刚开始学习归并排序算法的时候(递归),不夸张地说,一个下午都快磨完了。尽管本质的东西依然没能析透,但现在也有所理解。无他,唯手熟尔…道阻且长,奥利给!!!

你可能感兴趣的:(LeetCode刷题)