时间:2020-6-4
题目地址:https://leetcode-cn.com/problems/reverse-linked-list/
题目难度:Easy
题目描述:
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
思路1:使用额外的数据结构,反转数据结构
代码段1:通过
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if(head is None):
return None
temp = []
while(head):
temp.append(head.val)
head = head.next
temp.reverse()
head = ListNode(temp.pop(0))
start = head
while(temp):
temp2 = ListNode(temp.pop(0))
head.next = temp2
head = temp2
return start
总结:
- 面试时这么写,面试官100%会问你如何优化,比如不使用额外空间
思路2:使用双指针迭代
代码段2:通过
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
prev, curr = None, head
while curr:
temp = curr.next
curr.next = prev
prev = curr
curr = temp # cur.next, prev, cur = prev, cur, cur.next 相当秀的写法
return prev
总结:
- 双指针在链表结构操作非常好使
- 迭代写出来个这,这个头结点考虑的有点拧巴了【2021-02-07】
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if head == None:
return head
new_head = ListNode(head.val)
new_head.next = None
head = head.next
while head:
temp = ListNode(head.val)
temp.next = new_head
new_head = temp
head = head.next
return new_head
思路3:使用递归
关键点:head 的下一个节点指向head。
head.next.next = head
代码段3:通过
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if(head == None or head.next == None):
return head
new_head = self.reverseList(head.next)
head.next.next = head
head.next = None
return new_head
总结:
- 一看就会一写就懵的递归来了,递归处理时果断放弃了,简直是噩梦
- 依旧写不出来系列。还是得看描述,递归还是理解不透彻,加个图吧【2021-02-07】
递归和迭代:
递归:不断调用自身,等函数有返回才逐层返回,A调A,如:if else
两个规律:
- 递归函数必须要有终止条件,否则会出错;
- 递归函数先不断调用自身,直到遇到终止条件后进行回溯,最终返回答案。
迭代:不断循环,A调B,如:for while
递归中一定有迭代,但是迭代中不一定有递归,大部分可以相互转换。能用迭代的不用递归,递归调用函数,浪费空间,并且递归太深容易造成堆栈的溢出。
多练习,多理解