将单向链表按某个值划分成左边小、中间相等、右边大的形式 Python 版

本文介绍了一种链表划分算法,该算法能在O(n)的时间复杂度和O(1)的空间复杂度下,将单向链表按指定值分为三部分:小于该值的节点、等于该值的节点和大于该值的节点,并保持各部分内部节点的原始顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目
给定一个单向链表,如 LinkedList [21, 5, 120, 19, 72, 50, 312]。
再给定任意一个数值,比如50,返回一个链表,保证左边小、中间相等、右边大的形式,比如该例子的返回链表结果为:[21, 5, 19, 50, 120, 72, 312]

再比如给定值100,返回的链表结果为:[21, 5, 19, 72, 50, 120, 312]
且需要保证修改后的链表中,不论是左、中、右哪一部分结点的先后顺序和原链表中一致。

要求:时间复杂度为O(n),空间复杂度为O(1)。

代码

    def list_partition(head, pivot):
        '''
        将单向链表按某个值划分成左边小,中间相等,右边大的形式
        :param head:单向普通链表的头结点
        :param pivot:中间相等的那个数值
        :return:返回新的单向链表,左边和右边的结点顺序和原链表中的顺序一致。
        方法1:最常见的算法就是重新开辟三个链表,分别存储small ,middle,和large的值,时间复杂度为链表长度,空间复杂度也是
        方法2:把空间复杂度降到o(1),就是需要不停地调整链表中的位置
        '''
        if head == 0:
            print "This is an empty linked list."
            return
        sh, st, eh, et, lh, lt = 0, 0, 0, 0, 0, 0
        p = head
        while p != 0:
            if p.value < pivot:
                if sh == 0:
                    sh = p
                    st = p
                else:
                    st.next = p
                    st = st.next
            elif p.value == pivot:
                if eh == 0:
                    eh = p
                    et = p
                else:
                    et.next = p
                    et = et.next
            else:
                if lh == 0:
                    lh = p
                    lt = p
                else:
                    lt.next = p
                    lt = lt.next
            p = p.next

        if sh != 0 and eh != 0 and lh != 0:
            head = sh
            st.next = eh
            et.next = lh
            lt.next = 0
        elif sh == 0 and eh != 0 and lh != 0:
            head = eh
            et.next = lh
            lh.next = 0
        elif sh == 0 and eh == 0 and lh != 0:
            head = lh
            lh.next = 0
        elif sh == 0 and eh != 0 and lh == 0:
            head = eh
            et.next = 0
        elif sh != 0 and eh == 0 and lh == 0:
            head = sh
            st.next = 0
        elif sh != 0 and eh != 0 and lh == 0:
            head = sh
            st.next = eh
            et.next = 0
        elif sh != 0 and eh == 0 and lh != 0:
            head = sh
            st.next = lh
            lt.next = 0
        return head
分析
1、其实也没什么难度,主要就是操作一些结点指针变量来控制链表结点的指针域。分别存入三个链表,small,equal,large中,三个链表分别标注头尾两个指针。
2、并且要分情况讨论如果链表为空的情况。由于Python 里面没有 if else 语句的简写语法,所以必须一点点的把控制逻辑写出来。
### 实现链表合并并去除重复元素 为了实现这一目标,可以先创建一个辅助函数用于删除已排序链表中的重复元素。之后,在合并两个有序链表的过程中利用该辅助函数来移除可能出现的重复项。 对于链表节点定义如下: ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next ``` #### 合并与去重方法 首先按照常规方式完两者的合并操作[^3]。这里采用迭代的方法构建新的链表结构,并保持其顺序不变。接着遍历得到的新链表一次,检查相邻节点是否有相同的情况;如果发现有相同的,则跳过这些重复节点只保留第一次出现的那个节点。 下面是完整的 Python 代码示例: ```python def merge_and_remove_duplicates(l1: ListNode, l2: ListNode) -> ListNode: # 创建虚拟头结点简化边界条件处理 dummy_head = cur = ListNode(0) while l1 and l2: if l1.val < l2.val: cur.next = l1 l1 = l1.next elif l1.val > l2.val: cur.next = l2 l2 = l2.next else: # 当遇到相等时仅添加其中一个到结果列表中 cur.next = l1 l1 = l1.next l2 = l2.next cur = cur.next # 连接剩余部分 cur.next = l1 or l2 # 定义指针指向当前正在访问的节点及其前驱节点 prev, curr = None, dummy_head.next while curr is not None: # 如果存在前驱且两者数相等则忽略此节点 if prev and prev.val == curr.val: prev.next = curr.next else: prev = curr curr = curr.next return dummy_head.next ``` 这段程序实现了将两个升序排列的单向链表合并一个新的不含任何重复键的升序链表的功能[^5]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值