百度笔试题

笔试题

下面是来自于百度的编程笔试题,感兴趣的同学可以先自己想想解题思路:

你现在有一个文件,文件中顺序存有N个记录,R1,R2,...,RN,这些记录不是有序的,但是你知道一个整数M, 这些记录满足R1<R2<...<RM以及RM+1<RM+2<...RN.

1. 设计一个算法或编写一个程序,将文件中的记录排序为R1',R2',...,RN',算法或程序读取文件的次数为O(N),不限内存使用

2. 设计一个算法或编写一个程序,将文件中的记录排序为R1',R2',...,RN',算法或程序读写文件的次数为O(N),空间复杂度为O(1),亦即,你使用的内存大小和M,N均无关。

--------------我是华丽丽的分隔线----------------

内排序和外排序

根据在排序过程中待排序的记录是否全部被放置在内存中,排序可以分为内排序和外排序。

内排序是在排序整个过程中,待排序的所有记录全部被放置在内存中。外排序是由于排序的记录个数太多,不能同时放置在内存,整个排序过程需要在内外存之间多次交换数据才能进行。

排序算法的时间性能

排序算法的时间开销是衡量其好坏的最重要的标志。

在内排序中,主要进行两种操作:比较和移动。内排序算法的时间复杂度是比较次数加上移动次数的总和;

在外排序中,除了比较和移动,还有读写文件的操作。外排序算法的时间复杂度是比较次数,移动次数以及读写文件次数的总和。

高效率的排序算法应该是具有尽可能少的比较次数,移动次数及读写文件的次数。

排序算法的空间性能

评价排序算法的另一个主要标准是执行算法所需要的辅助存储空间。辅助存储空间是除了存放待排序所占用的存储空间之外,执行算法所需要的其他存储空间。

回到笔试题

基础知识介绍完毕,如果大家还有不明白的地方,可以先找找相关的资料参考一下。

5.1 对题目的理解

要解决一个问题,首先需要明确问题:

初始条件下,有N个数据数据都存放在一个文件中,并且有一个整数M,使得这些记录满足R1<R2<...<RM以及RM+1<RM+2<...RN。举一个例子来说,对于以下10N=10)个数23471015689),M2时,分成两个序列(23)和(471015689),由于第二个序列不是依次增大的,所以不满足条件。当M5时,分成两个序列234710)和(15689)都是依次增大,因此满足条件。

然后我们需要将这些记录排序,其实就是合并这两个子序列。以例子来看,其实就是需要把234710)和(15689)两个有序序列合并成(12345678910)一个有序序列。细心的同学可能会想起归并排序。是的,这个合并过程其实是归并排序中的一个子步骤。

题目的要求,第一个要求是读取文件次数为O(N),但是不限制内存的使用;第二个要求是读取文件次数为O(N),但是空间复杂度为O(1)。区别在于限不限制内存的使用。

如果不限制内存的使用,我们可以将文件中的内容全部读取到内存中,保存为数组,然后再对数组进行排序;如果限制内存的使用,我们可以采用外排序来解决这个问题,外排序一般会借助于文本文件。

最后的实现代码(java)如下:

/**

 * Sample code

 */

public class FileRecordSortMain {

    final static String SOURCE_FILE_NAME = "file.txt";

    final static String TEMP_FILE_NAME1 = "file_temp1.txt";

    final static String TEMP_FILE_NAME2 = "file_temp2.txt";

    final static int N = 10;

    final static int M = 5;

    /**

     * 第一种方法:

     * 将原文件中的记录顺序读取到内存中,以数组保存,然后以M为分隔将

     * 数组看为两组,互相比较两组元素之后输出,最后输出剩下的元素。

     * 

     * 性能分析:

     * 1. 时间复杂度是O(N),因为读取原文件N次,比较小于4N次,输出N次,

     * 加在一起的数量级是N的一次方

     * 2. 空间复杂度是N,因为将原文件中的记录事先读取到内存中,以数组

 * 保存,这个辅助空间的长度是N

     */

    static void sortInManner1() {

        //1. 将原文件中的记录顺序读取到内存中,以数组保存

        BufferedReader reader = getFileReader(SOURCE_FILE_NAME);

        int[] arry = new int[N];

        

        String str = "";

        int index = 0;

        try {

            while ((str=reader.readLine()) != null) {

                arry[index++] = Integer.valueOf(str);

            }

        } catch (IOException e) {

            e.printStackTrace();

        }

        

        //2. 将index<M数组元素看为一组,将index>=M的数组元素看为另一组

        //3. 互相比较两组元素,输出较小者,然后将较小者所在组的index+1

        int i = 0;

        int j = M;

        

        System.out.println("Sort Manner 1 Result:");

        

        while (i<M && j<N) {

            if (arry[i] < arry[j]) {

                System.out.print(arry[i++] + " ");

            } else {

                System.out.print(arry[j++] + " ");

            }

        }

        

        //4. 输出比较之后剩下来的元素

        while (i < M) {

            System.out.print(arry[i++] + " ");

        }

        

        while (j < N) {

            System.out.print(arry[j++] + " ");

        }

        

        System.out.println();

    }

    

    /**

     * 第二种方法:

     * 将原文件中的记录以M分隔,读取后保存到两个临时文件file_temp1.txt

     * 和file_temp2.txt中,然后将这两个临时文件中保存的数组看为两组,

     * 分别从这两个临时文件中读取元素,比较后输出,最后读取并输出剩下

     * 的元素。

     * 

     * 性能分析:

     * 1. 时间复杂度是O(N),因为读取原文件N次,写临时文件N次,读取临时

 * 文件N次,比较小于6N次,输出N次,加在一起是N的一次方

     * 2. 空间复杂度是1(与M,N均无关系),因为:

     * 在步骤1中,使用1个String和1个int作为辅助空间

     * 在步骤2,3,4中,使用1个String和1个String作为辅助空间,加在一起

 * 与M,N均无关系

     */

    static void sortInManner2() {

        //1. 将原文件中的记录以M分隔,读取后保存到两个临时文件

        //file_temp1.txt和file_temp2.txt

        BufferedReader sourceReader = getFileReader(SOURCE_FILE_NAME);

        BufferedWriter writer1 = getFileWriter(TEMP_FILE_NAME1);

        BufferedWriter writer2 = getFileWriter(TEMP_FILE_NAME2);

        

        String str = "";

        int index = 0;

        try {

            while ((str=sourceReader.readLine()) != null) {

                if (index < M) {

                    writer1.write(str+"\n");

                } else {

                    writer2.write(str+"\n");

                }

                ++index;

            }

        } catch (IOException e) {

            e.printStackTrace();

        } finally {

            try {

                writer1.close();

                writer2.close();

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

        

        //2. 将file_temp1.txt中的元素看为一组,将file_temp1.txt中的元

        //素看为另一组

        //3. 互相比较两组元素,输出较小者,然后继续从较小者所在的临时

        //文件中读取元素

        BufferedReader tempReader1 = getFileReader(TEMP_FILE_NAME1);

        BufferedReader tempReader2 = getFileReader(TEMP_FILE_NAME2);

        String numTemp1 = "";

        String numTemp2 = "";

        try {

            numTemp1 = tempReader1.readLine();

            numTemp2 = tempReader2.readLine();

            System.out.println("Sort Manner 2 Result:");

            

            while (numTemp1!=null && numTemp2!=null) {

                if (Integer.valueOf(numTemp1) < 

                        Integer.valueOf(numTemp2)) {

                    System.out.print(numTemp1 + " ");

                    numTemp1 = tempReader1.readLine();

                } else {

                    System.out.print(numTemp2 + " ");

                    numTemp2 = tempReader2.readLine();

                }

            }

            

            //4. 输出比较之后剩下来的元素

            while (numTemp1 != null) {

                System.out.print(numTemp1 + " ");

                numTemp1=tempReader1.readLine();

            }

            

            while (numTemp2 != null) {

                System.out.print(numTemp2 + " ");

                numTemp2=tempReader2.readLine();

            }

        } catch (IOException e) {

            e.printStackTrace();

        }

        

        System.out.println();

    }

    

    public static void main(String[] args) {

        sortInManner1();

        sortInManner2();

    }

    

    static BufferedReader getFileReader(String filename) {

        String souceFileAbsoluteName = getAbsolutePathName() + 

                File.separator + filename;

        

        InputStream is = null;

        BufferedReader reader = null;

        try {

            is = new FileInputStream(souceFileAbsoluteName);

            reader = new BufferedReader(new InputStreamReader(is));

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        }

        

        return reader;

    }

    

    static BufferedWriter getFileWriter(String filename) {

        String souceFileAbsoluteName = getAbsolutePathName() + 

                File.separator + filename;

        

        OutputStream os = null;

        BufferedWriter writer = null;

        try {

            os = new FileOutputStream(souceFileAbsoluteName);

            writer = new BufferedWriter(new OutputStreamWriter(os));

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        }

        

        return writer;

    }

    

    static String getAbsolutePathName() {

        File directory = new File("");

        return directory.getAbsolutePath();

    }

}

原文地址:https://www.cnblogs.com/FredCong/p/2787674.html