zoukankan      html  css  js  c++  java
  • 算法导论习题

    算法导论习题 9.1.1整型数组的次小值

    证明:在最坏情况下,利用n+ceil(lgn)-2次比较,即可得到n个元素中的第2小元素。(提示:同时找最小元素)
    补充说明:
    (1)这里的比较是只元素之间的比较。下标的比较是不算在内的。
    (2)ceil是向上取整的意思

    1. 思路解析

    1.1 总体思路解析

    具体思路解析参照女神 windmissing 的解析,看完之后思路会很清晰,windmissing同时也给出了 pythonc++版本的实现.

    下面给出 java 版本的实现 以及 代码解析

    1.2 代码思路分析

    数据结构 : 二叉树 + 链表

    为什么要使用链表呢?

    1. 解决这个问题需要在第一次遍历求最小值得时候, 从底向上 建立一颗二叉树; 就拿 最后一层来说吧, 最后一层的 成对(2个数) 的数比较之后,会形成二叉树的 倒数第二层 , 如果只是简单的使用二叉树结构, 我该怎么遍历这一层呢?

    2. 看来为了能在遍历 最后一层 之后, 接着遍历 倒数第二层, 迭代的建二叉树, 需要能遍历 倒数第二层, 在树的同一层,我们使用链表的结构,就能从头结点遍历的尾了.

    3. 嗯, 看来这样就能在第一次遍历的求最小值得时候建立一棵树了, 为了在第二步求 次小值 的时候简单一点, 你可以把树建成二叉搜索树(左孩子值 < 根节点值 < 右孩子值). 这样 次小值 就只会在最小值所在的 子树 右节点出现了.

    2.代码实现

    code

    package chapter9;
    
    /**
     * Created by NowGood on 2017/3/4.
     */
    public class Exercise911 {
    /**
    * head  当遍历某一层时, head 指向二叉树这一层的头结点, 当二叉树建立后, head 为树的根节点
    * child   孩子节点
    * parant  父节点;  两个孩子节点比较后,建立父节点 parent
    * firstPoint  遍历链表时, 成对的两个中的第一个
    * secondPoint  遍历链表时, 成对的两个中的第二个
    */
        BinaryNode head;
        BinaryNode child;
        BinaryNode parent;
        BinaryNode firstPoint;
        BinaryNode secondPoint;
        BinaryNode parentPoint;
    
    
    /**
    * 寻找最小元素, 建二叉树
    */
        public int firstSmall(int[] arr) {
            if (arr.length < 1 || arr == null)
                throw new RuntimeException("No data");
            if (arr.length == 1)
                throw new RuntimeException("No second  data");
    
            head = new BinaryNode(arr[0]);
            head.next = new BinaryNode(arr[1]);
            // 第一次处理数组,由于输入数组是整型,和后续处理的BinaryNode类不同不同,故设置tag = 1
            // 表示第一次处理, 并在第一次处理之后
            int tag = 1;
            while (head.next != null) {
                if (tag == 1) {
                        for (int i = 0; i < arr.length; i += 2) {
                        // 1. 奇数个元素,通过最后一个孩子节点直接建立父节点
                        // 2. 将两个数中较大的赋值给左孩子节点
                            if (i == arr.length - 1) {
                                child = new BinaryNode(arr[i]);
                                parent = new BinaryNode(arr[i]);
                                parent.leftChild = child;
                            } else if (arr[i] < arr[i + 1]){
                                parent = new BinaryNode(arr[i]);
                                parent.leftChild = new BinaryNode(arr[i]);
                                parent.rightChild = new BinaryNode(arr[i+1]);
                            }else {
                                parent = new BinaryNode(arr[i + 1]);
                                parent.leftChild = new BinaryNode(arr[i + 1]);
                                parent.rightChild = new BinaryNode(arr[i]);
                            }
                            if (tag == 1) {
                            // 自相向上建树, 获得上一层链表的头元素
                                head = parent;
                                parentPoint = parent;
                                tag = 0;
                            } else {
                            // 建立链表
                                parentPoint.next = parent;
                                parentPoint = parent;
                            }
                        }
                }
                
                // 打印建二叉树的过程
                BinaryNode x = head;
                while (x != null) {
                    System.out.print(x.element + " ");
                    x = x.next;
                }
                System.out.println();
                
                // 这里的处理过程和上面一样,只不过这里处理对象是 BinaryNode 链表,  上面是 int 数组
                firstPoint = head;
                head = null;
                while (firstPoint != null) {
                    //secondPoint 两个元素比较中 指向第二个元素的指针
                    secondPoint = firstPoint.next;
                    if (secondPoint == null) {
                        parent = new BinaryNode(firstPoint.element);
                        parent.leftChild = firstPoint;
                        firstPoint = firstPoint.next;
                    } else if (firstPoint.element < secondPoint.element){
                        parent = new BinaryNode(firstPoint.element);
                        parent.leftChild = firstPoint;
                        parent.rightChild = secondPoint;
                        firstPoint = secondPoint.next;
                    }else {
                        parent = new BinaryNode(secondPoint.element);
                        parent.leftChild = secondPoint;
                        parent.rightChild = firstPoint;
                        firstPoint = secondPoint.next;
                    }
                    if (head == null) {
                        head = parent;
                        parentPoint = parent;
                    } else {
                        parentPoint.next = parent;
                        parentPoint = parent;
                    }
                }
            }
              // 打印建二叉树的过程
            BinaryNode y = head;
            while (y != null) {
                System.out.print(head.element + " ");
                y = y.next;
            }
            System.out.println();
            return head.element;
        }
        
        // 寻找次小值
        public int secondSmall(int[] arr) {
            if (arr.length < 2)
                throw new RuntimeException("no second element");
            int firstSmall = firstSmall(arr);
            System.out.println("最小值为 :  " + firstSmall);
    
            int secondSmall = Integer.MAX_VALUE;
            while (head.leftChild != null) {
                if (head.rightChild == null) {
                    return secondSmall;
                }
                if (secondSmall > head.rightChild.element){
                    secondSmall = head.rightChild.element;
                }
                head = head.leftChild;
                }
            return secondSmall;
        }
    
    // 节点: 二叉树 + 链表
        private class BinaryNode {
            int element;
            BinaryNode next;
            BinaryNode leftChild;
            BinaryNode rightChild;
    
            public BinaryNode(int element) {
                this.element = element;
                next = null;
                leftChild = null;
                rightChild = null;
            }
        }
    }
    
    

    2.2 测试代码

    
    package chapter9;
    
    /**
     * Created by wangbin on 2017/3/4.
     * 测试代码
     */
    public class Test9 {
        public static void main(String[] args) {
            int[] a = {1, 4, 7, 9, 8};
            
            for (int i : a) {
                System.out.print(i + " ");
            }
            System.out.println();
            
            System.out.println("次小值为 :  " + new Exercise911().secondSmall(a));
        }
    }
    
    
  • 相关阅读:
    一种JavaScript的设计模式
    ADO.Net之使用DataRead Or DataSet
    求助:彻夜难眠的问题
    ASP.NET的全球化配置
    ADO.NET和.NET框架中的数据管理[转]
    javascript实现datagrid客户端checkbox列的全选,反选
    下载文件出现提示框或者直接显示在浏览器中
    Visual Studio .NET已检测到指定的Web服务器运行的不是ASP.NET 1.1 版..(转)
    网站优化的十大奇招妙技
    关键字加亮JS方法
  • 原文地址:https://www.cnblogs.com/nowgood/p/algs911.html
Copyright © 2011-2022 走看看