(一)Leetcode 25 每K个节点一组翻转链表
利用栈结构
首先能想到的当然是通过栈的结构,来进行反转,设置一个栈,先进后出的性质。唯一需要注意的当剩余的元素不足以放到栈里面的时候,就停止反转就好来。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
#用于链接头元素
Phead = ListNode(None)
p = Phead
while True:
count = k
stack = []
tmp = head
while count and tmp:
stack.append(tmp)
tmp = tmp.next
count -= 1
#跳出上面循环的时候,tmp是第k+1的元素来
#如果上面循环结束的时候,count还不为0,那就代表不足k个元素
if count :
p.next = head
break
#对k个元素进行反转
while stack:
p.next = stack.pop()
p = p.next
#与剩下链表链接起来
p.next = tmp
head = tmp
return Phead.next
尾插法
思路就是用一个指针指向头节点,一个指向尾部节点,让头节点连接尾部节点所连接的节点。然后让之前头部节点连接的节点,连接头部节点,一直到第一个节点为尾部节点。
eg,1,2,3,4,5,k=3,之前1连接的是2,现在让1,连接4,2之前连接的3,然后让他连接1,3之前连接4,现在连接2,然后让3成为头节点,从4开始往后继续。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
Phead = ListNode(None)
Phead.next, pre ,tail = head, Phead, Phead
while True:
count = k
while count and tail:
count -= 1
tail = tail.next
if not tail:break
head = pre.next
while pre.next!= tail:
#得到下一个元素
cur = pre.next
# pre与cur.next 连接起来,画图可以看出来
#cur是新的链表的第一个节点
pre.next = cur.next
cur.next = tail.next
#每次第一个节点都要知道插谁后面,这一句就是为了更新
tail.next = cur
#当前面都已经反转完毕,就要进行要一个k组的转换,需要更新,pre和tail
#按照k=3的例子,此时pre和tail就指向1这个节点,而我们第一步创建的pre和tail
#指向的是我们自己建立的节点
#感受一下建立一个新的头节点的好处
pre = head
tail= head
return Phead.next
递归法
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
cur = head
count = 0
while cur and count != k:
cur = cur.next
count += 1
#通过设置cur,把原先的链表切成几段,每一段在一个递归体里面进行处理。
if count == k:
cur = self.reverseKGroup(cur,k)
while count:
tmp = head.next
head.next = cur
cur = head
head = tmp
count -= 1
head = cur
return head
(二)Python实现链表反转
链表反转(while迭代实现):
-
链表的反转引入一个cur_node变量,表示当前节点;同时需要引入一个变量new_link表示反转后的新链表;while循环内还需中间变量tmp存放当前节点的后继节点,防止原链表数据丢失。
-
在while循环内(循环条件为 cur_node !=None,若设置为cur_node.next将导致最后一个节点无法反转到新链表):
- 首先需要将当前节点的后继节点传递给中间变量tmp
- 当前节点指向新链表new_link
- 当前节点指向新链表new_link后,新链表头结点更新为当前节点cur_node
- 将中间变量tmp传递给cur_node,开始新一轮循环
- 循环结束后返回 new_link
class Node(object):
def __init__(self, value=None, next=None):
self.value = value
self.next = next
@staticmethod
def reverse(head):
cur_node = head # 当前节点
new_link = None # 表示反转后的链表
while cur_node != None:
tmp = cur_node.next # cur_node后续节点传递给中间变量
cur_node.next = new_link # cur_node指向new_link
new_link = cur_node # 反转链表更新,cur_node为新的头结点
cur_node = tmp # 原链表节点后移一位
return new_link
link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8, Node(9)))))))))
root = Node.reverse(link)
while root:
print(root.value)
root =root.next
递归实现:
-
递归实现与while实现不同在于递归首先找到新链表的头部节点,然后递归栈返回,层层反转
-
首先找到新链表的头结点(即遍历到原链表的最后一个节点返回最后节点)
-
执行函数体后续代码,将原链表中的尾节点指向原尾节点的前置节点
-
前置节点的指针指向None(防止出现死循环)
-
返回新链表的头部节点至上一层函数,重复以上操作
def reverse2(self,head):
new_head = None
if head == None:
return None
if head.next == None: # 递归停止的基线条件
return head
new_head = self.reverseList(head.next)
head.next.next = head # 当前层函数的head节点的后续节点指向当前head节点
head.next = None # 当前head节点指向None
return new_head