1、假设一个客户,他的手机中存放有全中国人民的手机号,他的手机通信录顺序很乱而且里面可能有些重复了,现在客户想让我们设计一个程序,帮他把通讯录整理一下,删除重复手机号,说机上能利用的内存只有10M,但是有无限大的硬盘,请给出设计思路,并评估算法性能。
2、有一组数字,如14,26,5,30,0,-2,108,和一个给定的整数a,是否存在其中一个或几个,它们的和等于a。
请实现方法int findNIntendo(int arr[],int count,int a),存在返回1,否则返回0.
3、实现反转字符串。
4、以下关于红黑树的恶说法错误的是:
A、红黑树上插入操作的最差情况下的时间复杂度为O(log n)
B、红黑树上任意节点的左右子树高度差绝对不大于1
C、红黑树上删除操作最差情况的时间复杂度为O(log n)
D、红黑树上查找操作最差情况下的时间复杂度为O(log n)
5、unsigned short hash(unsigned short key){
return (key>>4)%256
}
请问hash(16),hash(256)的值分别是______、______
6、有98个元素的排序好的数组,用二分法查找,最多需要查找几次?
7、下列哪种排序算法和数据结构是不稳定的?
A、插入排序   B、快速排序   C、基数排序  D、(选项忘了)

解决方案 »

  1.   

    第一个:放到一个set里面,自动就删除重复的了。不过我想出题的人想考的应该是解题思路。
    我的思路是按手机号分别存放到不同的文件当中,比如132的放到一个文件中,133的放到一个文件中。
    遍历文件的时候,第一次遍历只读取132的,10M的空间存储132开头的手机号,重复的删除(Set集合就行了),最后剩余的存到132文件中。
    然后第二次遍历只读取133的,依次下去。
    第二个:我能想到的思路只有双层for循环了。算法就不写了,挺简单的,就是效率上有可能有点低。
    第三个:把字符串放到一个List或者map(key和字符成映射)中,遍历list的时候用反转遍历,map就按Key值从大到小读取呗。
    第四个:我不知道叫红黑树
    后面的先不做了,有空继续做。
      

  2.   

    第二道题不知道这样行不行
    import java.util.ArrayList;public class Find{
    public static final int MAX = 100;
    public static ArrayList<Integer> array = new ArrayList<Integer>(); public static void main(String[] args) {
    int arr[] = { 2, 4, 6, 7, 100 };
    int flag = findNIntendo(arr, 3, 110);
    System.out.println(flag);
    } public static int findNIntendo(int arr[], int count, int a) {
    int i;
    int[] a1 = new int[MAX];
    int[] b1 = new int[MAX];
    for (i = 1; i < 100; i++)
    a1[i - 1] = i;
    combine(a1, arr.length, count, b1, count,arr);
    for (int j = 0; j < array.size(); j++)
    if (array.get(j) == a)
    return 1;
    return 0;
    } public static void combine(int a[], int n, int m, int b[], int M,int[] arr) {
    int i, j; for (i = n; i >= m; i--) {
    b[m - 1] = i - 1;
    if (m > 1)
    combine(a, i - 1, m - 1, b, M,arr);
    else {
    int sum = 0; for (j = M - 1; j >= 0; j--)
    sum += arr[a[b[j]]-1];
    array.add(sum); }
    }
    }
    }
      

  3.   

    第三题:
    code=java]
    public class Test{
    public static void main(String[] args) {
    String str="54g34g34";
    char[] s;
    s=str.toCharArray();
    for(int i=s.length-1;i>=0;i--){
    System.out.print(s[i]);
    }
    }
    }[[/code]
    第四题还是不知道什么叫红黑树
    第五题:1,16
    hash(16)==>16>>4=1(把16转换为2进制数,然后退4位,就是等于16除以2的4次方)==>1%256余数等于1呗
    hash(256)等于16,也即是16除以256余数还是16
    第六题:取极端1,那就是分别和49,25,13,7,4,2比较。6次。至于最后一次需不需要和1比较,我不确定,还是回答6次至少证明你知道这个方法。
    第七题:快速排序是不稳定的,我也是刚查的,真不起大学时候的数据结构老师。
      

  4.   

    一般的,红黑树,满足以下性质,即只有满足以下全部性质的树,我们才称之为红黑树:1)每个结点要么是红的,要么是黑的。
    2)根结点是黑的。
    3)每个叶结点,即空结点(NIL)是黑的。
    4)如果一个结点是红的,那么它的俩个儿子都是黑的。
    5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。4.B、红黑树上任意节点的左右子树高度差绝对不大于1 感觉这个错误,还不确定。
      

  5.   

    第一题我的思路:
    // mobile = 11,person = 1300000000,momery=10M,
    double storeByte = 1300000000l * 11;//13亿人需要存储多少空间,11是手机号的字节数
    double memery = 10 * 1024 * 1024;//10M换算成字节数
    double splitCount = storeByte / memery;//做个小运算,看要读完全部数据到内存要做多少次
    1.以10M内存,需要进行计算1364次计算,才能完全处理完这些记录
    2.按每次10M处理现在手机号,发现重复的则删除,并记录成一个随机文件A1直到A1364
    3.读入A1文件到内存数组,读取A2-A1364文件,将A2到A1364一条记录(readLine)和A1记录比较,将不同结果写入新文件尾部考虑不周地方,欢迎批评
      

  6.   

    第一题:
    先HASH把号码划分成可以放入内存中操作的N分,存入N个文件中,再对每个文件进行操作。第二题:
    这个明显的是个经典的0-1背包问题。
    以下是动态规划实现
    int findNIntendoHelp(int arr[],int count,int left,stdext::hash_map<int,int> M,int c){
    if(M.find(left)!=M.end()){
    return M[left];
    }
    if(left==0){
    M[left]=1;
    return 1;
    }
    if(c>=count){
    M[left]=0;
    return 0;
    }
    if((findNIntendoHelp(arr,count,left-arr[c],M,++c)|findNIntendoHelp(arr,count,left,M,++c))==1){
            M[left]=1;
    return 1;
    }else{
    M[left]=0;
    return 0;
    }
    }
    int findNIntendo(int arr[],int count,int a){
        stdext::hash_map<int,int> M;
    int c=0;
    int left=a;
    return findNIntendoHelp(arr,count,left,M,c);
    }第三题:
    void inversestr(char* str){
    int r=strlen(str)-1;
    int l=0;char temp;
    while(r>l){
    temp=str[r];
    str[r--]=str[l];
    str[l++]=temp;
    }
    }第四题:
    B第五题:
    1 16第六题
    7次。第七题:
    快排第八题:
    看不清第九题:
    A第十题
    B
      

  7.   

    第一题:线程一:
    int start = 130 0000 0000 //可以赋值到线程target
    while(start++<131 0000 0000){
    //文件读取 选出收个和start相同的号码的记录。
    }
    考虑10M内存,以及程序的线程池、线程等资源消耗,综合控制线程数。
    第二题:看到某算法书上说此类问题可以递归解决。应该和背包问题一样吧。
    一点浅见,欢迎指正。
      

  8.   

    补充一下 题目都说了是中国人的手机号码,那就只有13X和15X 18X了
      

  9.   

    第二题:package com.zf.test;import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;/**
     * @author Administrator
     */
    public class CompomentTest { /**
     * @param array 要组合的源数组
     * @param n  以每n个元素作为一个组合
     * @param sum  组合内所有元素的和
     * @return 组合后的集合
     */
    public static  List<int[]> combination(int[] array , int n ,int sum){
    List<int[]> combinations = new ArrayList<int[]>();
    if(n <= 0 && n > array.length)
    return null ; LinkedList<Integer> tmp = new LinkedList<Integer>();
    for(int i = 0; i < array.length ;i++){
    if(i < n)
    tmp.add(1);
    else
    tmp.add(0);
    }
    boolean flag = true ;
    List<LinkedList<Integer>> indexgraph = new ArrayList<LinkedList<Integer>>();
    indexgraph.add(tmp);
    //得到所有元素的排列
    do{
    //寻找到第一个 1 0
    int last = tmp.get(0);
    int targetIndex = 1 ; for (; targetIndex <  tmp.size() ; targetIndex++) {
    int current = tmp.get(targetIndex) ;
    if( current == 0 && last == 1)
    break ;
    last = current;
    } if(targetIndex == tmp.size()) //已经排列完所有
    {
    flag = false;
    }
    if(flag){
    LinkedList<Integer> graph = new LinkedList<Integer>() ;
    for (int i = 0; i < targetIndex -1 ; i++) { //保存targetIndex之前的部分
    int l = tmp.get(i);
    if(l == 1)
    graph.addFirst(l);
    else
    graph.addLast(l);
    }
    graph.add(0);
    graph.add(1);
    for (int i = targetIndex + 1; i < tmp.size(); i++) {
    graph.add(tmp.get(i));
    }
    indexgraph.add(graph);
    tmp = graph ;
    }
    }while(flag); //从array中取出相对应的元素
    for (LinkedList<Integer> queue : indexgraph) {
    int[] t = new int[n];
    int index = 0 ;
    for (int i = 0; i < queue.size(); i++) {
    int k = queue.get(i);
    if(k == 1){
    t[index++] = array[i];
    }
    }
    combinations.add(t);
    }

    //取除所有元素之和不等于给定值的组合
    Iterator<int[]> it = combinations.iterator();
    while(it.hasNext()){
    int[] t = it.next();
    int s =  0 ;
    for (int i : t) {
    s+= i ;
    }
    if(s != sum){
    it.remove();
    }
    }
    return combinations ;
    }

    public static void main(String[] args) {

    List<int[]> result = combination(new int[]{0,1,2,3,4,5,8} , 3  , 10);

    for (int[] is : result) {   
    System.out.println(Arrays.toString(is));
    }
    }}运行结果:
    [2, 3, 5]
    [1, 4, 5]
    [0, 2, 8]
      

  10.   

    第一题应该用bitmap来实现,兄弟们去看看编程珠玑,上面有说这种题的!
      

  11.   

    第一题 :用两阶段多路归并排序的方法解决。假设手机号有N个,一个号约为10字节,首先将这N个手机号分成大小均为5M的小文件,则大概可以分为N*10/5000000=M份小文件,运行快速排序的方法对这M份小文件分别排序,然后每次从M份小文件中取出一个号码,得到M个号码,进行外排序,对于相同的号码不进行排序,排完后,输出到硬盘,算法完成。
    时间复杂度为O(nlogn)、空间复杂度为O(1)
    第二题 :该问题其实是一个子集和问题,即NP完全问题
    第三题 :定义两个指示器,一个指在最左边,向右移动,一个指在最右边,向左移动,两个指示器同时移动,直接相等。
    void invert_point(char *str)
    {
    int i,j;
    i=0;
    j=strlen(str)-1;
    while(i<j)
    {
    *(str+i)=*(str+i)^*(str+j);
    *(str+j)=*(str+i)^*(str+j);
    *(str+i)=*(str+i)^*(str+j);
    i++;
    j--;
    }
    }
    第四题:不知道
    第五题:hash(16),hash(256)的值分别是__1____、___16___
    如果short为一个字节,则hash(256)为0;如果short为两个字节,则hash(256)为16。
    第六题:7(2的7次方约等于98)
    第七题:B