zoukankan      html  css  js  c++  java
  • 关于java的杂乱无章(续更)

    • top K

    堆排解法
    用堆排来解决Top K的思路很直接。

    前面已经说过,堆排利用的大(小)顶堆所有子节点元素都比父节点小(大)的性质来实现的,这里故技重施:既然一个大顶堆的顶是最大的元素,那我们要找最小的K个元素,是不是可以先建立一个包含K个元素的堆,然后遍历集合,如果集合的元素比堆顶元素小(说明它目前应该在K个最小之列),那就用该元素来替换堆顶元素,同时维护该堆的性质,那在遍历结束的时候,堆中包含的K个元素是不是就是我们要找的最小的K个元素?

    实现:
    在堆排的基础上,稍作了修改,buildHeap和heapify函数都是一样的实现,不难理解。

    速记口诀:最小的K个用最大堆,最大的K个用最小堆。

    public class TopK {
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] a = { 1, 17, 3, 4, 5, 6, 7, 16, 9, 10, 11, 12, 13, 14, 15, 8 };
        int[] b = topK(a, 4);
        for (int i = 0; i < b.length; i++) {
            System.out.print(b[i] + ", ");
        }
    }
    
    public static void heapify(int[] array, int index, int length) {
        int left = index * 2 + 1;
        int right = index * 2 + 2;
        int largest = index;
        if (left < length && array[left] > array[index]) {
            largest = left;
        }
        if (right < length && array[right] > array[largest]) {
            largest = right;
        }
        if (index != largest) {
            swap(array, largest, index);
            heapify(array, largest, length);
        }
    }
    
    public static void swap(int[] array, int a, int b) {
        int temp = array[a];
        array[a] = array[b];
        array[b] = temp;
    }
    
    public static void buildHeap(int[] array) {
        int length = array.length;
        for (int i = length / 2 - 1; i >= 0; i--) {
            heapify(array, i, length);
        }
    }
    
    public static void setTop(int[] array, int top) {
        array[0] = top;
        heapify(array, 0, array.length);
    }
    
    public static int[] topK(int[] array, int k) {
        int[] top = new int[k];
        for (int i = 0; i < k; i++) {
            top[i] = array[i];
        }
        //先建堆,然后依次比较剩余元素与堆顶元素的大小,比堆顶小的, 说明它应该在堆中出现,则用它来替换掉堆顶元素,然后沉降。
        buildHeap(top);
        for (int j = k; j < array.length; j++) {
            int temp = top[0];
            if (array[j] < temp) {
                setTop(top, array[j]);
            }
        }
        return top;
    }
    

    }

    时间复杂度

    n*logK
    

    速记:堆排的时间复杂度是n*logn,这里相当于只对前Top K个元素建堆排序,想法不一定对,但一定有助于记忆。

    适用场景
    实现的过程中,我们先用前K个数建立了一个堆,然后遍历数组来维护这个堆。这种做法带来了三个好处:(1)不会改变数据的输入顺序(按顺序读的);(2)不会占用太多的内存空间(事实上,一次只读入一个数,内存只要求能容纳前K个数即可);(3)由于(2),决定了它特别适合处理海量数据。

    这三点,也决定了它最优的适用场景。

    快排解法
    用快排的思想来解Top K问题,必然要运用到”分治”。

    与快排相比,两者唯一的不同是在对”分治”结果的使用上。我们知道,分治函数会返回一个position,在position左边的数都比第position个数小,在position右边的数都比第position大。我们不妨不断调用分治函数,直到它输出的position = K-1,此时position前面的K个数(0到K-1)就是要找的前K个数。

    实现:
    “分治”还是原来的那个分治,关键是getTopK的逻辑,务必要结合注释理解透彻,自动动手写写。

    public class TopK {
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] array = { 9, 3, 1, 10, 5, 7, 6, 2, 8, 0 };
        getTopK(array, 4);
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + ", ");
        }
    }
    
    // 分治
    public static int partition(int[] array, int low, int high) {
        if (array != null && low < high) {
            int flag = array[low];
            while (low < high) {
                while (low < high && array[high] >= flag) {
                    high--;
                }
                array[low] = array[high];
                while (low < high && array[low] <= flag) {
                    low++;
                }
                array[high] = array[low];
            }
            array[low] = flag;
            return low;
        }
        return 0;
    }
    
    public static void getTopK(int[] array, int k) {
        if (array != null && array.length > 0) {
            int low = 0;
            int high = array.length - 1;
            int index = partition(array, low, high);
            //不断调整分治的位置,直到position = k-1
            while (index != k - 1) {
                //大了,往前调整
                if (index > k - 1) {
                    high = index - 1;
                    index = partition(array, low, high);
                }
                //小了,往后调整
                if (index < k - 1) {
                    low = index + 1;
                    index = partition(array, low, high);
                }
            }
        }
    }
    }
    

    时间复杂度

    n
    

    速记:记住就行,基于partition函数的时间复杂度比较难证明,从来没考过。

    适用场景
    对照着堆排的解法来看,partition函数会不断地交换元素的位置,所以它肯定会改变数据输入的顺序;既然要交换元素的位置,那么所有元素必须要读到内存空间中,所以它会占用比较大的空间,至少能容纳整个数组;数据越多,占用的空间必然越大,海量数据处理起来相对吃力。

    但是,它的时间复杂度很低,意味着数据量不大时,效率极高。

    好了,两种解法写完了,赶紧实现一下吧。

    java中比较两个日期的大小

    String beginTime=new String("2014-08-15 10:22:22"); 
    String endTime=new String("2014-09-02 11:22:22"); 
    

    1.把字符串类型的日期数据转化成长整型,然后比较大小。
    如果日期格式有时分秒,则”-“写成”[-s:]”

    if(Long.valueOf(beginTime.replaceAll(“-“,”“)
    

    2.直接进行字符串比较
    beginTime.compareTo(endTime)<0时,开始时间小于结束时间

    注意:如果一个日期格式是2016-01-01,但是另一个日期格式是2016-1-1时,直接使用字符串进行比较就会存在问题。

    3.用SimpleDateFormat转化成日期型再判断

    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); 
      Date bt=sdf.parse(beginTime); 
      Date et=sdf.parse(endTime); 
      if (bt.before(et)){ 
       //表示bt小于et 
      }else{ 
       --反之 
      } 
    

    比较日期的先后:

    DateTime str1date = new DateTime(str1,DateTime.YEAR_TO_DAY); 
    DateTime str2date = new DateTime(str2,DateTime.YEAR_TO_DAY); 
    

    1.直接比较

    if (str1date.before(str2date)){ 
    //表示str1date小于str2date 
    }else{ 
    --反之 
    } 
    

    2.用 date.getTime() 返回long相加减或直接比较用大于小于号比较或者用compareTo

    3.SimpleDateFormat的format方法将日期型转化成时间或日期的字符串,然后再比较字符串。

                                                <未完>
    
  • 相关阅读:
    Populating Next Right Pointers in Each Node II
    Populating Next Right Pointers in Each Node
    Construct Binary Tree from Preorder and Inorder Traversal
    Construct Binary Tree from Inorder and Postorder Traversal
    Path Sum
    Symmetric Tree
    Solve Tree Problems Recursively
    632. Smallest Range(priority_queue)
    609. Find Duplicate File in System
    poj3159最短路spfa+邻接表
  • 原文地址:https://www.cnblogs.com/pigdata/p/10305545.html
Copyright © 2011-2022 走看看