案例三
链表的分化
题干:
对于一个链表,我们需要用一个特定阈值完成对它的分化,使得小于等于这个值的结点移到前面,大于该值的结点在后面,同时保证两类结点内部的位置关系不变。
给定一个链表的头结点head,同时给定阈值val,请返回一个链表,使小于等于它的结点在前,大于等于它的在后,保证结点值不重复。
* 测试样例:
* {1,4,0,,2,5},3
* {1,0,2,4,5}
解析:这是一个经典的荷兰过期问题,只是在这里要求在链表中完成;通过维护三个链表来完成,具体如下
小于链表、等于链表、大于链表
在维护的时候需要通过指针记录小于链表的尾部,需要通过指针记录等于链表的头部和尾部,需要通过指针记录大于链表的头部。
最后就可以通过以上的四个指针将三个链表连在一起。
class Node:
def __init__(self,data):
self.data = data
self.next = None
class LinkList:
def __init__(self):
self.head = None
def sort(self,arr,num):
if not arr:
return None
headmix = self.head #小于等于链表的头指针
mix = None #小于等于链表的尾指针
headmax = self.head #大于链表的头指针
maxx = None #大于链表的尾指针
#将数组中的元素创建节点链接到p上去
for i in range(len(arr)):
newNode = Node(arr[i])
if not self.head:
self.head = newNode
p = self.head
else:
p.next = newNode
p = newNode
p = self.head
while p:
if p.data <= num:
if not headmix:
headmix = p
mix = headmix
else:
mix.next = p
mix = mix.next
if p.data > num:
if not headmax:
headmax = p
maxx = headmax
else:
maxx.next = p
maxx = maxx.next
p = p.next
if headmix == None:
maxx.next = None
self.printlist(headmax)
# return headmax
elif headmax == None:
mix.next = None
self.printlist(headmix)
#return headmix
else:
mix.next = headmax
maxx.next = None
self.printlist(headmix)
# return headmix
def printlist(self,q):
while q:
print(q.data)
q = q.next
我这里写的时候是写了测试用例的,所以写了遍历链表的函数,如果是OJ环境下,可以不用写
案例四
打印两个链表的公共值
现有两个升序链表,且链表中均无重复元素。请设计一个高效的算法,打印两个链表的公共值部分。
给定两个链表的头指针head1和head2,请返回一个vector,元素为两个链表的公共部分。请保证返回数组的升序。两个链表的元素个数均小于等于500。保证一定有公共值
* 测试样例:
* {1,2,3,4,5,6,7},{2,4,6,8,10}
* 返回:[2.4.6]
#这是没有测试用例的
class Node:
def __init__(self,data):
self.data = data
self.next = None
class Solution:
def print_same(self,head1,head2):
while head1!=None and head2!=None:
if head1.data < head2.data:
head1 = head1.next
elif head1.data > head2.data:
head2 = head2.next
else:
print(head1.data)
head1 = head1.next
head2 = head2.next
# 这是有测试用例的,里面有如何生成链表的头结点的方法
class Node:
def __init__(self,data):
self.data = data
self.next = None
class Linklist:
def __init__(self):
self.first = self.last = None
def insert_end(self,data):
newNode = Node(data)
if not self.last:
self.first = self.last = newNode
else:
self.last.next = newNode
self.last = newNode
class Solution:
def create_link(self,arr):
link = Linklist()
for item in arr:
link.insert_end(item)
return link
def print_same(self,arr1,arr2):
if len(arr1)==0 or len(arr2)==0:
return
link1 = self.create_link(arr1)
link2 = self.create_link(arr2)
p = link1.first
q = link2.first
while p!=None and q!=None:
if p.data < q.data:
p = p.next
elif p.data > q.data:
q = q.next
else:
print(p.data)
p = p.next
q = q.next
arr1 = [1,2,3,4,5,6,7]
arr2 = [2,4,6,8,10]
test = Solution()
test.print_same(arr1,arr2)
案例五
链表的k逆序练习题
给定一个单链表的头结点head,实现一个调整单链表的函数,使每K个结点之间逆序,
若最后不够K个节点一组,则不调整最后几个节点。
测试用例:
1 2 3 4 5 6 7 8, k=3
调整为3 2 1 6 5 4 7 8
解题思路:
如果使用栈的话,时间复杂度为O(n),空间复杂度为O(k),而且要留意最后不满k个的结点,要正序输出
在这里我采用每遍历k个元素就逆序,时间复杂度为O(n),空间复杂度为O(1)
个人感觉这个算法的整体思路特别清晰,但是真正实现起来的时候,很多细节需要注意
class Node:
def __init__(self,data):
self.data = data
self.next = None
class Linklist:
def __init__(self):
self.first = self.last = None
def create_linklist(self,arr):
if not arr:
return
for i in range(len(arr)):
newNode = Node(arr[i])
if not self.first:
self.first = self.last = newNode
else:
self.last.next = newNode
self.last = newNode
return self.first
def reverse(self,arr,k):
head = self.create_linklist(arr)
if not head:
return
if k<2:
return head
pcur = head #正在遍历的当前节点
pstart = None
ppre = None
pnext = None #待遍历的下一个节点
count = 1
while pcur:
pnext = pcur.next
if count == k:
if ppre == None:
pstart = head
head = pcur
else:
pstart = ppre.next
self.resign(ppre,pstart,pcur,pnext)
ppre = pstart
count = 0
count += 1
pcur = pnext
return head
def resign(self,left,start,end,right):
ppre = start
pcur = start.next
pnext = None
while pcur != right:
pnext = pcur.next
pcur.next = ppre
ppre = pcur
pcur = pnext
if left:
left.next = end
start.next = right