3、反转链表
反转一个单链表。
示例:
输入:1 -> 2 -> 3 -> 4 -> 5 -> NULL
输出:5 -> 4 -> 3 -> 2 -> 1 -> NULL
解法1:迭代
思路:从前往后遍历链表,定义3个指针分别指向相邻的三个节点,反转前两个节点,即让第二个节点指向第一个节点。然后一次往后移动指针,直到第二个节点为空结束。
class Solution:
def reverseList(self, head):
preNode = None
while head:
nextNode = head.next
head.next = preNode
preNode = head
head = nextNode
return preNode
解法2:递归
基线条件:空链或只有一个节点,直接返回头指针
递归条件:递归调用,返回子链表反转后的头指针
class Solution:
def reverseList(self, head):
if not head or not head.next:
return head
nextNode = head.next
newHead = self.reverseList(nextNode)
nextNode.next = head
head.next = None
return newHead
4、合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1 -> 2 -> 4, 1 -> 3 -> 4
输出:1 -> 1 -> 2 -> 3 -> 4 -> 4
解法1:
思路:创建一个新的链表,按顺序将 l 1 、 l 2 l1、l2 l1、l2 接上。
class Solution:
def mergeTwoLists(self, l1, l2):
head = ListNode(0)
newlist = 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
head.next = l1 or l2
#newlist一直指着头部,从0开始,所以要从下一个开始return
return newlist.next
解法2:递归
先判断 l 1 、 l 2 l1、l2 l1、l2 是否为空的情况,若都不为空,再采用递归方法分别比较 l 1 、 l 2 l1、l2 l1、l2 中的节点。
class Solution:
def mergeTwoLists(self, l1, l2):
if l1 == None and l2 == None:
return None
if l1 == None:
return l2
if l2 == None:
return l1
if l1.val <= l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
5、回文链表
请判断一个链表是否为回文链表。
示例1:
输入: 1 -> 2
输出:False
示例2:
输入:1 -> 2 -> 2 -> 1
输出:True
思路:
- 采用快慢指针找到链表中点:用追赶法,一个指针一次走两步,一个指针一次走一步;
- 找到中点后,将后半链表反转。
注意:反转过程中,nextNode = slow.next一定要在第二句,而不是最好,不然会断链- 判断链表是否为回文链表
class Solution:
def isPalindrome(self, head):
fast = slow = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
node = None
while slow:
nextNode = slow.next
slow.next = node
node = slow
slow = nextNode
while node and head:
if node.val != head.val:
return False
node = node.next
head = head.next
return True
新建一个链表,判断反转后是否相等
class Solution:
def isPalindrome(self, head):
stack = []
while head:
stack.append(head.val)
head = head.next
return stack == stack[::-1]
4、环形链表
给定一个链表,判断链表中是否有环。
设置两个指针slow和fast,一个步长为1、一个步长为2进行遍历。如果有环,slow和fast总会在某一点相遇;如果没有,则fast会先为空或fast.next为空。
class Solution(object):
def hasCycle(self, head):
fast = slow = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if slow == fast:
return True
return False
关于环形链表问题的总结:
- 快慢指针一直到相遇时的循环次数等于环的长度。
两者相遇在慢指针走了一圈时。
因为slow的速度代表的是链表基本的长度单位,即从一个节点移动到下一个节点的距离。当循环结束时,slow走了1圈,正好是环的长度。 - 快慢指针相遇点到环入口的距离=链表起始点到环入口的距离。