zoukankan      html  css  js  c++  java
  • 2016年1月15日面试某互联网公司总结(二)

      首先,感谢大家的浏览,还有朋友给推荐工作,由于本人目前在北京,且年后本人在北京还有部分课程需要上,因此现在不便于远行前往深圳,广州等地。还是非常感谢大家!

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

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

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

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

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

       数据库中存储数据的基础单位就是页,数据库的页大小和操作系统类似,是指存放数据时,每一块的大小。比如一个1M的数据存放在数据库中时, 需要大概12块页来存放。如果是在操作系统上安装的数据库,最好将数据库页大小设置为操作系统页大小的倍数,才是最佳设置。数据库可以将数据从逻辑上分成页,磁盘的I/O操作就是在页级执行。

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

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

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

    非聚集索引与聚集索引之间的显著差别在于以下两点:

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

      索引的优点:正确的索引会大大提高数据查询,对结果进行排序、分组的操作效率。
        索引的缺点:
        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 + ":	");
                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 + "	");
            }
            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("排序前:		");
            merge.printAll(array);
    //        merge.sort(array);
            merge.mSort(array,0,array.length-1);
            System.out.print("排序后:		");
            merge.printAll(array);
        }
    }

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

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

  • 相关阅读:
    C# 文件类的操作---删除
    C#实现Zip压缩解压实例
    UVALIVE 2431 Binary Stirling Numbers
    UVA 10570 meeting with aliens
    UVA 306 Cipher
    UVA 10994 Simple Addition
    UVA 696 How Many Knights
    UVA 10205 Stack 'em Up
    UVA 11125 Arrange Some Marbles
    UVA 10912 Simple Minded Hashing
  • 原文地址:https://www.cnblogs.com/accipiter/p/5138162.html
Copyright © 2011-2022 走看看