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


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

      

      给定一个单向链表的头节点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;
        }
    }
  • 相关阅读:
    jQuery邮箱验证
    查看图片前进后退效果
    jQuery实现全选与反选
    jQuery在p前后添加节点
    jQuery中的fadeIn、fadeOut、fadeTo的应用
    jQuery中图片隐藏效果的所有方法
    jQuery中animate的应用(图片自动移动)
    jQuery图片复制
    N!具体数值有多少位数字
    顺序队列的初始化,建立,插入,查找,删除。
  • 原文地址:https://www.cnblogs.com/Demrystv/p/9321021.html
Copyright © 2020-2023  润新知