似乎有很多套卷子, 我的是C卷, 笔试题有4页双面纸, 12道题, 涉及SQL, 数据挖掘基本概念, 数据结构及算法, java, SAS宏编程, 广告价格差异化等. 手机会被锁进"养机箱"中, 233333.

问题


1. 请简述什么是数据库的笛卡尔集?
包含两个集合中任意取出的两个元素构成的所有组合的集合.假设集合R中有元组M个, 集合S中有元组N个, 则R和S的笛卡尔积中包含的元组数量就是M*N. 这个规则可向多个关系扩展. 例如:  
d1=(a,b);  d2=(1,2,3);
d1 X d2=(a1,a2,a3,b1,b2,b3)
2. 用SQL语句对A表和B表进行操作, 得到C表.
  • A表
Name Height
Jack 190
Jacy 180
Rick 175
Tim 185
John 170
  • B表
Name Height
Raive 176
Shine 168
  • C表
Name Height
Jack 190
Jacy 180
John 170
Raive 176
Shine 168
Tim 185
观察ABC表可知, C表为A表和B表的合并, 且按Name升序排序, 并去除Rick. SQL代码为:
select * from A where Name<>'Rick'
union
select * from B
order by Name asc;
3. 有表emp, 格式为 { 姓名,工号,职位类型,工资,部门 }, 请用SQL语句得到:
a) 每个部门的最高薪资和最低薪资是多少.
b) 职位类型为XXX的每个部门的最高工资
c) 高于本部门的平均薪资的所有人的姓名, 工资和部门
查询每个部门的语句 group by, 平均数的函数avg(), 最高数的函数max(), 最低数的函数min(). 
  • a) 使用嵌套表查询
select 薪资,部门 from emp where
   (薪资,部门) in (select max(薪资), 部门 from emp group by 部门)
or
   (薪资,部门) in (select min(薪资), 部门 from emp group by 部门);
  • b) 跟a一样, 多了个职位类型
select 薪资,部门 from emp where
   职位类型='xxx'
and
   (薪资,部门) in (select max(薪资), 部门 from emp group by 部门);
  • c) 嵌套表+avg()的使用
select 姓名,工资,部门 from emp where
   薪资 > (select avg(薪资) from emp where 部门='本部门');

4. 聚类有什么作用, 请简述聚类的思想及算法.
聚类就是将物理或抽象对象的集合分成由类似的对象组成的多个类的过程. 这些对象与同一个簇Cluster中的对象彼此相似, 与其他簇中的对象相异.
  这里记录划分法: Partitioning Methods, 对于给定的K, 算法首先给出一个初始的分组方法, 以后通过反复迭代的方法改变分组, 使得每一次改进之后的分组方案都教前一次好, 所谓"好"的标准是: 同一分组中的记录越近越好, 不同分组中的记录越远越好.
  划分法中较经典的算法有K-means:
  1. n个数据中任选k个为k个Cluster的中心.
  2. 遍历剩余n-k个对象, 计算与这k个中心的距离, 加入离其最近的一个.
  3. 每个簇求质心, 将7个质心作为新的cluster.
  4. 重复2-3步, 直到质心收敛.

聚类是不知道有几类, 因此k的选定很重要. 而分类是已经知道有几类, 如kNN算法(k-NearestNeighbor which is belong to lazy learning) 和下一题的朴素贝叶斯.
5. 朴素贝叶斯的算法与思想, 并简述其缺点是什么.
Naive Bayes Classifier, 简称NBC.
 由概率论的全概率公式, 条件概率公式推出贝叶斯公式. (以后会有专题博客, 这里不详细展开)
 之所以称之为朴素, 是因为假定了 属性之间相互独立. 于是这也是其缺点.
6. 某银行一直以来用一些算法(如逻辑回归和决策树)预测客户的违约情况, 得到很好的效果, 但是近年来的预测度下降, 请给出解决该问题的思路.
个人见解: 由测不准原理, 银行预测了哪些客户会违约, 不贷款给他们, 于是他们会"进化"成满足条件的贷款者, 而这些条件并不能保证他们不违约, 因此他们拿到贷款后便仍会违约. 解决方案: 换新的算法, 或者调新的参数. 在模拟预测后, 再推广.
7. 求根号2, 不准直接调用函数或者API, 请用文字或代码描述, 若用代码请注明所用语言.
这道题我第一印象就是用二分法, 然后像高数的求极限一样, 给定一个精度ε, 当满足其绝对值小于此精度ε时, 则输出结果. 后来查了一下, 这就是<数值分析>课上的"牛顿迭代法". 用C语言写. 
float low=0, high=2, mid, epsilon;
epsilon=0.001; // 假设精度为0.001
mid = (low+high)/2;
int noFinish = 1;
while(noFinish) {
    if(mid*mid>2) {
        if(mid*mid - 2 < epsilon) { 
        // 若mid的平方大于2且与2相差满足精度要求, 则输出
            printf("The result is %f\n", mid); 
            break;
        }
        low = mid;
    }
    if(mid*mid<2) {
        if(2 - mid*mid < epsilon) { // 同上
            printf("The result is %f\n", mid);
            break;
        }   
        high = mid;
    }
    if(mid*mid==2) // 不排除能得到刚好平方等于2的数,
        printf("The result is %f\n", mid);
    mid = (low+high)/2; // 取中间值继续运行
}

8. 排序算法的思想, 用文字或代码描述, 若用代码请注明所用语言.参考链接
这道题我用文字和画图的方法, 描述了一个快排的思想, 若有和版面, 还可以写直接插入, 选择插入, 希尔排序, 冒泡排序, 堆排序, 归并排序, 外排序等算法. 在这里用C语言描述一下快排. 
    #include <stdio.h>
    #include <stdlib.h>

    void swap(int *x,int *y)
    {
       int temp;
       temp = *x;
       *x = *y;
       *y = temp;
    }

    int choose_pivot(int i,int j )
    {
       return((i+j) /2);
    }

    void quicksort(int list[],int m,int n)
    {
       int key,i,j,k;
       if( m < n)
       {
          k = choose_pivot(m,n);
          swap(&list[m],&list[k]);
          key = list[m];
          i = m+1;
          j = n;
          while(i <= j)
          {
             while((i <= n) && (list[i] <= key))
                    i++;
             while((j >= m) && (list[j] > key))
                    j--;
             if( i < j)
                    swap(&list[i],&list[j]);
          }
         // 交换两个元素的位置
          swap(&list[m],&list[j]);
         // 递归地对较小的数据序列进行排序
          quicksort(list,m,j-1);
          quicksort(list,j+1,n);
       }
    }

    void printlist(int list[],int n)
    {
       int i;
       for(i=0;i<n;i++)
          printf("%d\t",list[i]);
    }

    void main()
    {
       const int MAX_ELEMENTS = 10;
       int list[MAX_ELEMENTS];

       int i = 0;

       // 产生填充序列的随机数
       for(i = 0; i < MAX_ELEMENTS; i++ ){
         list[i] = rand();
       }
       printf("进行排序之前的序列:\n");
       printlist(list,MAX_ELEMENTS);

       // sort the list using quicksort
       quicksort(list,0,MAX_ELEMENTS-1);

       // print the result
       printf("使用快速排序算法进行排序之后的序列:\n");
       printlist(list,MAX_ELEMENTS);
    }
9. 给出以下java代码, 请写出输出结果, 为什么?
public class MyBasic{
    public void MyBasic() {
        System.out.println("MyBasic...");
    }
}
public class Test extends MyBasic {
    public void Test() {
        System.out.println("Test...");
    }
    public static void main(String[] args) {
        new Test();
        new MyBasic();
    }
}
这道题做的时候是懵逼的, 因为一直很讨厌臃肿的java, 笔试完后问了大仙森, 他通俗易懂地解释了java的类继承时, 父类子类的解析顺序:
    1. 父类的static
    2. 子类的static
    3. 父类的非static & 非构造函数
    4. 父类的构造函数
    5. 子类的非static & 非构造函数
    6. 子类的构造函数
    故这道题的输出结果为:
    MyBasic...    // 顺序4, 父类的构造函数, 在new Test()时
    Test...    // 顺序6, 子类的构造函数, 在new Test()时
    MyBasic... // 在new MyBasic时
10. 请写出输出结果. (这道题忘了具体的SAS宏代码, 但是只要会一门基础语言, 都可以写出来吧)
 给出一些简单的SAS宏编程做参考.
%marco asdf(a,s,d,f);     // marco是SAS的宏
%put &a &s &d f;          // put是输出, 输出a,s,d的值, 以及字符f
%mend;                    // end of marco

%asdf(1,2,3,4);

输出结果为: 1, 2, 3, f
11. 网页布局中(如图), 请写出ABCD四个地区的广告价格差异化, 为什么?

(note: WordPress加载图片名称不能为中文)

不论是横屏还是竖屏, C位置的广告肯定第一个被注意到. 所以C的价格应该最高.
其次, A和B位置的广告, 比如很多人浏览网页和看小说时, 往往懒得关闭, 因此存活时间最长, 故此两位置的价格次之.
最后, D位置的广告, 既不显眼, 也没法存活太久(往往都会关掉), 因此价格最低.
综上所述, ABCD四处的价格差异为C>A=B>D.

有其他见解的, 欢迎留言探讨.

12. 给出高速公路的广告牌价格差异化方案, 并说出理由.
跟上一题差不多, 广告价格的定价标准取决于: 受众数量, 广告时间, 刺激强度 三个方面. (自己的见解, 有专业看法欢迎讨论)
因此在经常塞车的地方, 车流量大的地方, 广告位的价格高.
在车流量小, 或者流畅的地方, 广告位的价格低.

总结


这是第一次出去面试, 其实只要勇敢地踏出象牙塔一步, 后面的都很简单. 刚开始搭车出去很紧张, 去到广州也很紧张, 看到笔试题那一刻也是懵逼的, 但是想着我又不必全部答对, 也不必一次就拿到offer, 刚出来社会能经济独立够生活就好, 于是就坦然了. 直到做完笔试, 发现我笔试竟然过了. 不过还要电话面试, 静静等候吧.