1、IBM面试题:平面上画1999条直线,最多能将平面分成多少部分?
分析:
没有直线时有一个空间;(1)
1条直线时,这条这些可以将这个空间分成两个;(1+1)
2条直线时,第二条直线可以和第一条直线相交,这样第二条直线可以将两个空间分成四个;(1+1+2)
....
注意到画每条直线时能增加多少个空间,取决于此直线从多少个空间中通过。
而从多少个空间中通过,取决于和多少条直线相交。
例如,如果一条直线和其它5条直线相交,那么最大可以通过6个空间,此直线可以增加6个子空间。
画每条直线时,能相交的直线数为总的已经画过的直线。
所以总的空间数最多为
1+1+2+3+...+1999 = 1999001
2、IBM面试题:使用两根烧1小时的香,确定15分钟的时间
不均匀分布的香,每根香烧完的时间是一个小时,你能用什么方法来确定一段15分钟的时间?
分析:第一根点燃两头,第二根只点一头。
当第一根烧完时,时间过去了30分钟,所以第二根还能烧30分钟。这时点燃第二根的另外一头,第二根香还能烧的时间就是15分钟。
3、IBM面试题:27个人去买矿泉水
有27个人去买矿泉水,商店正好在搞三个空矿泉水瓶可以换一瓶矿泉水的活动,他们至少要买几瓶矿泉水才能每人喝到一瓶矿泉水?
分析:19
4、百度面试题:将多个集合合并成没有交集的集合
给定一个字符串的集合,格式如:{aaa bbb ccc}, {bbb ddd},{eee fff},{ggg},{ddd hhh}要求将其中交集不为空的集合合并,要求合并完成后的集合之间无交集,例如上例应输出{aaa bbb ccc ddd hhh},{eee fff}, {ggg}。
(1)请描述你解决这个问题的思路;
(2)请给出主要的处理流程,算法,以及算法的复杂度
(3)请描述可能的改进。
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.util.Arrays;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.ListIterator;
- import java.util.regex.Pattern;
-
-
-
-
-
-
-
- public class BaiDu_UnionStringSet {
- static String ReadString() throws IOException {
-
- String s = new String();
- BufferedReader stdin = new BufferedReader(new InputStreamReader(
- System.in));
- System.out
- .println("输入格式如{aaa bbb ccc},{bbb ddd},{eee fff},{ggg hhh},{ddd hhh}的字符串:");
- s = stdin.readLine();
- stdin.close();
- return s;
- }
-
- static String[][] String_to_List(String s) {
-
- List list;
- String ss = new String();
- s = s.replace("{", "").replace("}", "");
- list = Arrays.asList(Pattern.compile(",").split(s));
- String[][] sz = new String[list.size()][3 * list.size()];
- for (int i = 0; i < list.size(); i++) {
- ss = (String) list.get(i);
- sz[i] = Pattern.compile(" ").split(ss);
- }
- return sz;
- }
-
- static boolean ComStr(String[] s1, String[] s2) {
-
- int i, j;
- for (i = 0; i < s1.length; i++)
- for (j = 0; j < s2.length;) {
- if (s1[i] != null && s2[j] != null && s1[i].equals(s2[j])) {
- return true;
- } else
- j++;
- }
- return false;
- }
-
- static boolean belong(String s, String[] s1) {
-
- for (int i = 0; i < s1.length;) {
- if (s1[i] != null) {
- if (s.equals(s1[i]))
- return true;
- else
- i++;
- } else
- i++;
- }
- return false;
- }
-
- static String[] MergeStr(String[] s1, String[] s2) {
-
- String[] s = new String[s1.length + s2.length];
- int i, j;
- for (i = 0; i < s1.length; i++)
- s[i] = s1[i];
- for (i = 0, j = 0; j < s2.length; j++) {
- if (s1 != null && s2[j] != null) {
- if (!belong(s2[j], s1)) {
- s[s1.length + i] = s2[j];
- i++;
-
- }
- }
- }
- return s;
- }
-
- static void findUnion(String[][] s) {
-
- int i, j;
- for (i = 0; i < s.length; i++) {
- for (j = 0; j < s.length; j++) {
- if (s[i] != null && s[j] != null && i != j) {
- if (ComStr(s[i], s[j])) {
- s[i] = MergeStr(s[i], s[j]);
- s[j] = null;
- }
- }
- }
- }
- for (int k = 0; k < s.length; k++) {
- if (s[k] != null) {
- OutPutString(s[k]);
- }
- }
- }
-
- static void OutPutString(String[] str) {
- System.out.println("使用冒泡排序:"+"\n"+SortString_bubbling(RemoveNull(str)));
- System.out.println("使用插入排序:"+"\n"+SortString_insert(RemoveNull(str)));
- }
-
- static List RemoveNull(String[] str) {
- List nonull_list = new LinkedList();
- for (int i = 0; i < str.length; i++) {
- if (str[i] != null) {
- nonull_list.add(str[i]);
- }
- }
- return nonull_list;
- }
-
- static List SortString_bubbling(List list) {
-
- String s1 = new String();
- String s2 = new String();
- for (int i = 0; i < list.size(); i++) {
- for (int j = i; j < list.size(); j++) {
- s1 = list.get(i).toString();
- s2 = list.get(j).toString();
- if (s1.compareTo(s2) > 0) {
- list.set(i, s2);
- list.set(j, s1);
- }
- }
- }
- return list;
- }
-
- static List SortString_insert(List list) {
-
- List sortedlist = new LinkedList();
- ListIterator x = list.listIterator(0);
- String str = new String();
- String comstr = new String();
- String comstr_a = new String();
- int count, moveid, flag;
- while (x.hasNext()) {
- str = x.next().toString();
- flag = -1;
- for (count = 0; flag == -1 && count < sortedlist.size(); count++) {
- if (sortedlist.size() == 0) {
- sortedlist.set(count, str);
- flag = 0;
- } else {
- comstr = sortedlist.get(count).toString();
- if (str.compareTo(comstr) < 0) {
- for (moveid = sortedlist.size(); moveid > count; moveid--) {
- comstr_a = sortedlist.get(moveid - 1).toString();
- if (moveid == sortedlist.size()) {
- sortedlist.add(moveid, comstr_a);
- } else
- sortedlist.set(moveid, comstr_a);
-
- }
- sortedlist.set(count, str);
- flag = 0;
- }
- }
- }
- if (flag == -1) {
- sortedlist.add(str);
- flag = 0;
- }
- }
- return sortedlist;
- }
-
- public static void main(String[] args) throws IOException {
- findUnion(String_to_List(ReadString()));
- }
- }

4、网易面试题:new/delete和malloc/free的区别
new/delete和malloc/free的区别,并说说你在什么情况下会自另行建立自己的内存分配。
解析:
new/delete:给定数据类型,new/delete会自动计算内存大小,并进行分配或释放。如果是对类进行操作,new/delete还会自动调用相应的构造函数和析构函数。
malloc/free:没有进行任何数据类型检查,只负责分配和释放给定大小的内存空间。
有些情况下,new/delete和malloc/free都不能满足性能的要求,我们需要自建内存分配来提高效率。比如,如果程序需要动态分配大量很小的对象,我们可以一次分配可以容纳很多小对象的内存,将这些小对象维护在链表中,当程序需要时直接从链表中返回一个。
5、百度面试题:有两个文件,各含50M和500个url,找出共同的url
一个大的含有50M个URL的记录,一个小的含有500个URL的记录,找出两个记录里相同的URL。
解析:
首先使用包含500个url的文件创建一个hash_set。
然后遍历50M的url记录,如果url在hash_set中,则输出此url并从hash_set中删除这个url。
所有输出的url就是两个记录里相同的url。(复杂度为:O(m×n))
AC自动机算法也可以解决。参见:http://www.cppblog.com/mythit/archive/2009/04/21/80633.html
6、微软面试题:删除链表中的重复项
一个没有排序的链表,比如list={a,l,x,b,e,f,f,e,a,g,h,b,m},请去掉重复项,并保留原顺序,以上链表去掉重复项后为newlist={a,l,x,b,e,f,g,h,m},请写出一个高效算法(时间比空间更重要)。
解析:
建立一个hash_map,key为链表中已经遍历的节点内容,开始时为空。
从头开始遍历链表中的节点:
- 如果节点内容已经在hash_map中存在,则删除此节点,继续向后遍历;
- 如果节点内容不在hash_map中,则保留此节点,将节点内容添加到hash_map中,继续向后遍历。
- import java.util.HashMap;
- import java.util.LinkedList;
- import java.util.Map;
- public class hashmap_noduplicates {
- static void removeduplicates(String[] str)
- {
- LinkedList list = new LinkedList();
- Map hm=new HashMap();
- String s=new String();
- int flag=0;
- for (int i = 0; i < str.length; i++) {
- list.add(str[i]);}
- for(int counter=0;counter<str.length;counter++){
- s=str[counter];
- if(!hm.containsKey(s)){hm.put(s, null);}
- else {
- list.remove(counter-flag);
- flag++;
- }
- }
- System.out.println(list);
- }
-
- public static void main(String[] args){
- String[] str={"a","l","x","b","e","f","f","e","a","g","h","b","m"};
- removeduplicates(str);
- }
- }
7、谷歌面试题:找到两个字符串的公共字符,并按照其中一个的排序
写一函数f(a,b),它带有两个字符串参数并返回一串字符,该字符串只包含在两个串中都有的字符并按照在a中的顺序。写一个版本算法复杂度O(N^2)和一个O(N) 。
解析:
O(N^2):
对于a中的每个字符,遍历b中的每个字符,如果相同,则拷贝到新字符串中。
O(N):
首先使用b中的字符建立一个hash_map,对于a中的每个字符,检测hash_map中是否存在,如果存在则拷贝到新字符串中。
- import java.util.HashMap;
-
-
- public class find_samechars {
- static String find_samechars_n2(String s1,String s2){
- char[] c1=s1.toCharArray();
- char[] c2=s2.toCharArray();
- char c;
- String s=new String();
- int i,j,flag;
- for(i=0;i<c1.length;i++){
- c=c1[i];
- flag=-1;
- for(j=0;flag==-1 && j<c2.length;j++){
- if(c==c2[j]){flag=0;}
- }
- if(flag==0){s=s+c;}
- }
- return s;
- }
- static String find_samechars_n(String s1,String s2){
- HashMap hm=new HashMap();
- String s=new String();
- char[] c1=s1.toCharArray();
- char[] c2=s2.toCharArray();
- for(int i=0;i<c2.length;i++){
- hm.put(c2[i],null);
- }
- for(int j=0;j<c1.length;j++){
- if(hm.containsKey(c1[j])){s=s+c1[j];}
- }
- return s;
-
- }
- public static void main(String[] args){
- String s1="ijklmnabcdefgh";
- String s2="azbyixhwgvcn";
- System.out.println("s1="+s1);
- System.out.println("s2="+s2);
- System.out.println("时间复杂度为N^2:"+find_samechars_n2(s1,s2));
- System.out.println("时间复杂度为N:"+find_samechars_n(s1,s2));
- }
- }

8、谷歌面试题:如何尽快找到一个好人
有n个人,其中超过半数是好人,剩下的是坏人。好人只说真话,坏人可能说真话也可能说假话。这n个人互相都知道对方是好人还是坏人。
现在要你从这n个人当中找出一个好人来,只能通过以下方式:
每次挑出两个人,让这两个人互相说出对方的身份,你根据两个人的话进行判断。
问通过何种方法才能最快的找出一个好人来。(要考虑最坏的情况)
解析:
先找一个人A,然后其他所有人评价A
1如果半数说A是好人:A是好人
2如果半数以上说A是坏人:A是坏人
-----
如果A是坏人
去掉说A是好人的人(一定是坏人)
在剩下的人里找一个人重复上面的(这里好人肯定更多于一半)
---
递归进行
最坏情况就是坏人都说实话且每次运气不好都选出的是坏人
这时复杂度是O(n^2)
实际计算时选出好人的几率越来越高的,因为坏人不断的被去掉
(好吧,我承认我的智商太低了)