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

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

  

  给定一个单向链表的头节点head,节点的值类型是整数,再给定一个整数 pivot,实现一个调整链表的函数,使得左半部分的值都是小于pivot的节点,中间部分都是等于pivot的节点,右边部分都是大于pivot的节点,对于左半部分、中间、右半部分内部的顺序没有要求。

  如果对于三部分内部的顺序也是有要求,即内部顺序各个节点的顺序与原来链表中的各个节点的先后顺序相同。

  【解析】

  普通问题:

  首先遍历一遍链表,得到链表的长度,将链表元素依次放到数组中,然后利用类似于快速排序中的partition 思想进行分割。

  进阶问题:

  1.将链表分为三部分:small,equal,big

            small:1->2->null

            equal:5->5->null

            big:9->8->null

  2.将small、equal、big三个链表重新串起来

  3.整个过程需要特别注意对null节点的判断和处理

  

package com.test;

import com.test.ListNode;

/**
 * Created by Demrystv.
 */
public class ListNodePartition {

    /**
     * 普通问题
     * 时间复杂度是 O(N),空间复杂度是 O(N)
     */
    /*
    首先遍历一遍链表,得到链表的长度,将链表元素依次放到数组中,然后利用类似于快速排序中的partition 思想进行分割
     */
    public ListNode listPartition1(ListNode head, int pivot){
        if (head == null){
            return head;
        }
        int i = 0;
        ListNode cur = head;
        while (cur != null){
            i++;
            cur = cur.next;
        }

        // 将链表中的每个元素依次放入到数组中
        ListNode[] nodeArr = new ListNode[i];
        i = 0;
        cur = head;
        for (i = 0; i != nodeArr.length; i++){
            nodeArr[i] = cur;
            cur = cur.next;
        }
        // 进行类似快速排序的partition
        arrPartition(nodeArr,pivot);

        // 重新连接各个链表节点
        for (i = 1; i != nodeArr.length; i++){
            nodeArr[i - 1].next = nodeArr[i];
        }
        nodeArr[i - 1].next = null;
        return nodeArr[0];
    }

    public void arrPartition(ListNode[] nodeArr, int pivot){
        int small = -1;
        int big = nodeArr.length;
        int index = 0;
        while (index != big){
            if (nodeArr[index].val < pivot){
                swap(nodeArr, ++small, index);
            }else if (nodeArr[index].val == pivot){
                index++;
            }else {
                swap(nodeArr, --big, index);
            }
        }
    }

    public void swap(ListNode[] nodeArr, int a, int b){
        ListNode temp = nodeArr[a];
        nodeArr[a] = nodeArr[b];
        nodeArr[b] = temp;
    }

    /**
     *  进阶问题: 保证各部分内部的顺序与原来链表中各个节点的顺序相同
     *  时间复杂度是 O(N),空间复杂度是 O(1)
     *  考察 利用有限的几个变量来调整链表的代码实现能力。
     */
    /*
    1.将链表分为三部分:small,equal,big
                      small:1->2->null
                      equal:5->5->null
                      big:9->8->null
    2.将small、equal、big三个链表重新串起来
    3.整个过程需要特别注意对null节点的判断和处理
     */
    public ListNode listPartition2(ListNode head, int pivot){

        // 将链表分为small、equal、big
        ListNode sH = null;
        ListNode sT = null;
        ListNode eH = null;
        ListNode eT = null;
        ListNode bH = null;
        ListNode bT = null;
        ListNode next = null;// 保存下一个节点

        //将所有的节点依次保存在三个链表中
        while (head != null){
            // 将head节点独立出来
            next = head.next;
            head.next = null;

            if (head.val < pivot){
                if (sH == null){
                    sH = head;
                    sT = head;
                }else {
                    sT.next = head;
                    sT = head;
                }
            }else if (head.val == pivot){
                if (eH == null){
                    eH = head;
                    eT = head;
                }else {
                    eT.next = head;
                    eT = head;
                }
            }else {
                if (bH == null){
                    bH = head;
                    bT = head;
                }else {
                    bT.next = head;
                    bT = head;
                }
            }
            head = next;
        }

        // 小的和相等的重新连接
        if (sT != null){
            sT.next = eH;
            eT = eT == null ? sT : eT;
        }
        // 所有的重新连接
        if (eT != null){
            eT.next = bH;
        }

        // 判断头节点是否为空
        return sH != null ? sH : eH != null ? eH :bH;
    }
}

原文地址:https://www.cnblogs.com/Demrystv/p/9321021.html

时间: 2024-08-12 20:54:14

链表问题----将单向链表按某值划分成左边小、中间相等、右边大的形式的相关文章

左神算法书籍《程序员代码面试指南》——2_07将单向链表按某值划分成左边小、中间相等、右边大的形式

Problem:[题目] 给定一个单向链表的头节点head,节点的值类型是整型,再给定一个整数pivot. 实现一个调整链表的函数,将链表调整为左部分都是值小于 pivot的节点, 中间部分都是值等于pivot的节点,右部分都是值大于 pivot的节点. 除这个要求外,对调整后的节点顺序没有更多的要求. 例如:链表9->0->4->5->1,pivot = 3. 调整后链表可以是1->0->4->9->5, 可以是0->1->9->5-&g

复习下C 链表操作(单向链表)

Object-C 作为C 的包装语言(运行时.消息机制).如果不熟悉C 的话实在玩得太肤浅. 随便深入oc 内部都会接触到C. runtime .GCD.Block.消息机制... 所有强大的功能无不用的 包装体(struct 结构体).使用GCC/Clang (可以google 下.Clang 比GCC 更优化,) 编译指令. 转换OC 为 C . 终端 使用Clang 命令参考 clang -rewrite-objc file.m 查看file.cpp 文件为编译转换的C 单向链表 创建 .

数据结构和算法--链表一之单向链表的简单实现

链表在我们java中也是一种基础的数据结构,可以理解成是一种和数组同级的数组结构,正如我们所知,在我们使用这集合ArrayList和LinkedList的时候,总会学习底层数组实现的ArrayList和双向链表实现的LinkedList的区别.在这里,我们将要讲说的是单向链表的简单实现,让我们体会一下链表在实现增删改查的时候是怎么样的一个操作,在和前边涉及到的数组的增删改查进行对比,得到我们学习的结论,数组的增删效率低于链表结构,查改效率高于链表结构! 什么叫做单向链表,我们可以理解为一个一个节

C#学习单向链表和接口 IList&lt;T&gt;

作者:乌龙哈里 时间:2015-11-04 平台:Window7 64bit,Visual Studio Community 2015 参考: MSDN 索引器(C# 编程指南) <数据结构(C#语言版)>下载 When to use IEnumerable, ICollection, IList and List 章节: 单向链表元素 定义单向链表操作接口 逐步实现单向链表 正文: 前面学习了 IEnumerable<T>.IComparable<T>.ICollec

【转】单向链表(单链表)的Java实现

最近被问到链表,是一个朋友和我讨论Java的时候说的.说实话,我学习编程的近一年时间里,学到的东西还是挺少的.语言是学了Java和C#,关 于Web的学了一点Html+css+javascript.因为比较偏好,学习WinForm时比较认真,数据库操作也自己有所研究.但链表这个东西我 还真没有学习和研究过,加上最近自己在看WPF,而课程也到了JSP了,比较紧. 但是我还是抽了一个晚上加半天的时间看了一下单向链表.并且使用Java试着写了一个实例出来.没有接触过链表的朋友可以作为参考,希望大家多提

数据结构-线性表之单向链表--一点一滴

单向链表 单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始. 单向链表的数据结构可以分为两部分:数据域和指针域,数据域存储数据,指针域指向下一个储存节点的地址.分为动态单向链表和静态单向链表.单向链表也可以根据是否带头节点分为带头节点结构和无带头节点结构.我们把指向单链表的指针为头指针.头指针所指的不存放数据元素的第一个节点称作头节点.存放数据元素的节点成为第一个数据元素节点. 注:第一个数据元素节点在带头节点单链表中是第二个节点:而在不带头节

写给过去的自己-No.1-数据结构篇-单向链表C语言的实现

过去的自己,你好.     今天我来教你单向链表,不知道你何时会看到这篇文章,也不知道你此刻对C语言的掌握,我会尽可能讲解细一点.     讲链表之前我先讲一下数组.相信你不管怎样肯定用过数组对吧,数组就是一种数据的组织形式,特点是所有的数据在逻辑上是顺序摆放的,通过数组名和数组下标 就可以找到某个元素,而且在内存中存放的物理地址也是连续的,定义数组时,一旦中括号中的数字确定了,数组中元素个数也就确定了.那么问题来了,因为数组 的大小需要提前确定,所以定义数组时必须统计好程序中用了多少元素,用多

单向链表的简单使用

一.单向链表的概念 单向链表是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始.链表是使用指针进行构造的列表,并且是由一个个结点组装起来的,因此又称为结点列表.其中每个结点都有指针成员变量指向列表中的下一个结点,head指针指向第一个结点称为表头,而终止于最后一个指向nuLL的指针. 结点的数据结构 [objc] view plain copy print? typedef struct _LINK_NODE { int data; struct _LINK_NO

数据结构与算法学习-单向链表的实现

链表(Chain本文所说链表均为单向链表,以下均简称单向链表)实际上是由节点(Node)组成的,一个链表拥有不定数量的节点.而向外暴露的只有一个头节点(Head),我们对链表的所有操作,都是直接或者间接地通过其头节点来进行的. 节点(Node)是由一个需要储存的对象及对下一个节点的引用组成的.也就是说,节点拥有两个成员:储存的对象.对下一个节点的引用. 这样说可能大家不是很明白,我贴一张图大家可能更容易理解. package LinkedList; /** * <p><strong>