直通BAT面试算法精讲--链表(2)

案例三

链表的分化
题干:
对于一个链表,我们需要用一个特定阈值完成对它的分化,使得小于等于这个值的结点移到前面,大于该值的结点在后面,同时保证两类结点内部的位置关系不变。
给定一个链表的头结点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
    原文作者:Andyato0520
    原文地址: https://blog.csdn.net/yato0514/article/details/81455269
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞