2016年1月15日面试某互联网公司总结(二)

  首先,感谢你们的浏览,还有朋友给推荐工做,因为本人目前在北京,且年后本人在北京还有部分课程须要上,所以如今不便于远行前往深圳,广州等地。仍是很是感谢你们!html

  今天主要是把以前的工具,作了一些设置与调整,工欲善其事,必先利其器嘛。主要涉及到Eclipse设置maven使用(以前工做都是使用自有构建工具,如今用开源,开源工具功能大而全,可是,每每也坑比较多),git工具的使用(之前工做一直使用SVN,版本管理之后稍做介绍),Mysql安装使用(以前工做一直使用oracle,关于这一部分之后作详加使用说明)。下面仍是接昨天的,把面试涉及到的东西写完整。java

====================================华丽分割线===========================================git

1.索引的使用,联合索引的使用,是否索引越多越好?面试

答:[以oracle为例]索引比如是一本书前面的目录,能加快数据库表的查询速度。索引分为聚簇索引非聚簇索引两种,聚簇索引 是按照数据存放的物理位置为顺序的,而非聚簇索引就不同了;聚簇索引能提升多行检索的速度,而非聚簇索引对于单行的检索很快。sql

   用的最多也最好的是B-tree索引,它主要是避免了大量数据的排序操做。数据库

   数据库中存储数据的基础单位就是页,数据库的页大小和操做系统相似,是指存放数据时,每一块的大小。好比一个1M的数据存放在数据库中时, 须要大概12块页来存放。若是是在操做系统上安装的数据库,最好将数据库页大小设置为操做系统页大小的倍数,才是最佳设置。数据库能够将数据从逻辑上分红页,磁盘的I/O操做就是在页级执行。数组

  • 96字节大小的标头,存储统计信息,包括页码、页类型、页的可用空间以及拥有该页的对象的分配单元 ID。数据库页类型主要分以下三类:
      • 数据页,除了大型对象的数据列以外的数据存储页,好比int,float,varchar等。     
      • 索引页,存放索引的条目。
      • 大型对象数据类型,好比text,image,nvarchar(max)等。        
  • 一个区包含8个页,它是管理空间的单位,分为以下两类
    • 统一区,由单个对象全部。
    • 混合区,最多可由八个对象共享

  知道了区以及页的概念,再看下数据表和这二者之间的联系, 表包含一个或多个分区,每一个分区在一个堆或一个汇集索引结构中包含数据行。oracle

  索引中的底层节点称为叶节点。根节点与叶节点之间的任何索引级别统称为中间级。在汇集索引中,叶节点包含基础表的数据页。根节点和中间级节点包含存有索引行的索引页。每一个索引行包含一个键值和一个指针,该指针指向 B -树上的某一中间级页或叶级索引中的某个数据行。每级索引中的页均被连接在双向连接列表中。maven

非汇集索引与汇集索引之间的显著差异在于如下两点:函数

  • 基础表的数据行不按非汇集键的顺序排序和存储。
  • 非汇集索引的叶层是由索引页而不是由数据页组成。

  索引的优势:正确的索引会大大提升数据查询,对结果进行排序、分组的操做效率。
    索引的缺点:
    1.建立索引须要额外的磁盘空间,索引最大通常为表大小的1.2倍左右。
    2.在表数据修改时,例如增长,删除,更新,都须要维护索引表,这是须要系统开销的。
    3.不合理的索引设计非但不能利于系统,反而会使系统性能降低。例如咱们在一个建立有非汇集索引的列上作范围查询,此列的索引不会起到任何的优化效果,反而因为数据的修改而须要维护索引表,从而影响了对数据修改的性能。

什么字段不适合建立索引?
    1.不常用的列,这种索引带来缺点远大于带来的优势。

    2.逻辑性的字段,例如性别字段等等,匹配的记录太多,和全表扫描比起来差很少。

    3.字段内容特别大的字段,例如大字段等,这会大大增大索引所占用的空间以及索引维护时的速度。

  4.涉及到计算的列,或者是须要利用数据库函数进行加工处理的列不该当建立索引。

联合索引:

1.查询条件中出现联合索引第一列,或者所有,则能利用联合索引.

2.条件列中只要条件相连在一块儿,不管先后,都会利用上联合索引.

3.查询条件中没有出现联合索引的第一列,而出现联合索引的第二列,或者第三列,都不会利用联合索引查询.

单一列索引:

  1.只要条件列中出现索引列,不管在什么位置,都能利用索引查询.

另外,实际使用过程当中,常常遇到索引丢失的状况,这种状况通常须要重建索引,有的涉及到复杂业务查询的语句,须要优化查询,对于具体的SQL,可能因为优化的缘由,有不是理想的执行计划。

======================================华丽分割线==========================================

2.实现二路归并排序(面试是要求画出图)

 答:二路归并理解起来比较容易,主要是利用分治法。可是,具体代码仍是要下一些功夫。

  核心思想:将待排序序列R[0...n-1]当作是n个长度为1的有序序列,将相邻的有序表成对归并,获得n/2个长度为2的有序表;将这些有序序列再次归并,获得n/4个长度为4的有序序列;如此反复进行下去,最后获得一个长度为n的有序序列。

归并排序其实要作两件事:

  1.分解——将序列每次折半划分

  2.合并——将划分后的序列段两两合并后排序

   合并的规则:

  在每次合并过程当中,都是对两个有序的序列段进行合并,而后排序。这两个有序序列段分别为 arr[low, mid] 和 arr[mid+1, high]。先将他们合并到一个局部的暂存数组tmparr中,待合并完成后再将tmparr复制回R中。这里称 arr[low, mid] 第一段,arr[mid+1, high] 为第二段。每次从两个段中取出一个记录进行关键字的比较,将较小者放入tmparr中。最后将各段中余下的部分直接复制到tmparr中。通过这样的过程,tmparr已是一个有序的序列,再将其复制回arr中,一次合并排序就完成了。

  注意,若子表个数为奇数,则最后一个子表无须和其余子表归并(即本趟处理轮空):若子表个数为偶数,则要注意到最后一对子表中后一个子表区间的上限为n-1。 

/**
* @FileName MergeSort.java
* @Package com.algorithm.sort
* @Description 
* <li>二路归并排序,它相对与快排序和堆排序来讲,是稳定的排序方法,时间复杂度o(nlnn),空间复杂度为o(n)</li>
* @Author ali blog:http://www.cnblogs.com/accipiter
* @Date 上午1:06:31
* @Version V1.0.1
*/
package com.algorithm.sort;
/**
* @ClassName MergeSort
* @Description TODO
* @Date 下午11:14:51
 */
public class MergeSort {
    /**
    * @Title Merge
    * @Description TODO
    * @param arr
    * @param low
    * @param mid
    * @param high 
    * @Return void
    * @Throws 
    * @user Administrator
     */
    public void merge(int[] arr, int low, int mid, int high) {
        int i = low; // i是第一段序列的起始
        int j = mid + 1; // j是第二段序列的起始
        int k = 0; // k是临时存放合并序列的起始
        int[] tmparr = new int[high - low + 1]; // tmparr是临时合并序列
        while (i <= mid && j <= high) {
            if (arr[i] <= arr[j]) {
                tmparr[k++] = arr[i++];
            } else {
                tmparr[k++] = arr[j++];
            }
        }
        while (i <= mid) {
            tmparr[k++] = arr[i++];
        }
        while (j <= high) {
            tmparr[k++] = arr[j++];
        }
        for (k = 0, i = low; i <= high; i++, k++) {
            arr[i] = tmparr[k];
        }
    }
    /**
    * @Title MergeStep
    * @Description TODO
    * @param arr
    * @param len
    * @param length 
    * @Return void
    * @Throws 
    * @user Administrator
     */
    public void mergeStep(int[] arr, int len, int length) {
        int i = 0;
        for (i=0;i+ 2*len-1<length;i+=2*len){
            merge(arr,i, i+len-1, i+ 2*len-1);
        }
        if (i+len-1<length){
            merge(arr,i, i+len-1,length-1);
        }
    }
    /**
    * @Title sort
    * @Description TODO
    * @param list
    * @return 
    * @Return int[]
    * @Throws 
    * @user Administrator
     */
    public int[] sort(int[] list) {
        for (int len = 1; len < list.length; len = 2 * len) {
            mergeStep(list, len, list.length);
            System.out.print("len = " + len + ":\t");
            this.printAll(list);
        }
        return list;
    }
    /**
    * @Title printAll
    * @Description TODO
    * @param list 
    * @Return void
    * @Throws 
    * @user Administrator
     */
    public void printAll(int[] list) {
        for(int value : list){
            System.out.print(value + "\t");
        }
        System.out.println();
    }
    /**
    * @Title MSort
    * @Description 
    * <li>纯递归实现二路归并排序</li>
    * @param arr
    * @param low
    * @param high 
    * @Return void
    * @Throws 
    * @user Administrator
     */
    public void mSort(int []arr,int low,int high){
        if(low<high){
            int mid=(low+high)/2;
            mSort(arr,low,mid);
            mSort(arr,mid+1,high);
            merge(arr,low,mid,high);
            this.printAll(arr);
        }
    }
    public static void main(String[] args) {
        int[] array = { 8, 1, 7, 3, 1, 2, 6, 9, 5};
        MergeSort merge = new MergeSort();
        System.out.print("排序前:\t\t");
        merge.printAll(array);
//        merge.sort(array);
        merge.mSort(array,0,array.length-1);
        System.out.print("排序后:\t\t");
        merge.printAll(array);
    }
}

 

==================================华丽分割线=============================================

这次面试主要内容就以上,再也不深究了。接下来一段时间,我会利用好,出一些系列的东西,也想本身实现点东西。感谢支持!

相关文章
相关标签/搜索