昨天的JAVA面试题,感觉挺难大家帮忙看看!新手第一次发帖!
2.1 下图是电话机键盘

从图中,我们可以发现26个字母分布在2-9这8个数字键上。某人的电话号码是65967427,观察单词“olympics”,可以发现:字母o位于数字键6上,字母l位于数字键5上,… 字母s 位于数字键7上。此时,我们说olympics是65967427对应的一个字母组合。65967427还可以对应其它很多种字母组合,例如:mjwmpgap也是其中之一。以C语言编写函数 :int transfer(int number)。该函数的输入为一个电话号码(允许输入为3位到11位的十进制数),在屏幕上输出该数字对应的所有字母组合,并返回组合的总数。如果数字中包含1或者0,由于没有与之对应的字母,则直接返回0。当数字小于3位或者大于11位时,亦没有对应字母组合,返回0。

2.2 求解:有一个文本文件,记录了某个学校所有人的姓名、出生日期(假设没有人重名,该校大约有2万人)。记录格式如下:
。。。。。。
张三 19800120
李四 19810321
王五 19800122
赵六 19830321
。。。。。。
现在需要在某天举办一场生日晚会,邀请生日在当天的人员参加。如果期望这场生日晚会参加的人员尽可能多,那么应该选择在哪一天?在解答时,需要注意代码的效率、质量。当不能给出完整代码时,可以描述解题思路。


2.3求解:在一份文本文件中,查找其中所有的anagram。例如,如果这份文件中包含了stop、tops、pots这样三个单词,这三个词就是一组anagram,这三个单词都是由s、t、o、p这四个字母组成的。这份文件中可能存在多组anagram,大小写视为同样字符。在解答时,需要注意代码的效率、质量。当不能给出完整代码时,可以描述解题思路。
评论
renyangok 2008-06-16
Underwind 写道

3,为了提高效率,必须设计一个方法 long calc(String word),该方法保证位置不同但字母相同的单词能返回同样的值,而字母不同的单词肯定返回不同的值(题目中没有明确说明是否考虑字母重复的情况,比如as和ass,故此方法也不考虑)。

这个方法可以利用两个不同质数的乘积是唯一的这个数学特性来实现,让字母a-z对应从3开始的质数,然后取乘积。



这样,文章中的每一个单词都有了对应的计算值,计算值相同的单词要么是重复的,要么就是anagram(变位词)。



时间复杂度:对文章进行一次遍历。

空间:需要与单词个数等大的辅助空间。


万一出现个超长单词:1913个字母,“色氨酸合成酶A蛋白质”(一种含有267种氨基酸酶)的化学名:

MethionylglutaminylarginyltyrosylglutamylserylleucylphenylalanylalanylglutaminylleucyllysylglutamylarginyllysylglutamylglycylalanylphenylalanylvalylprolyphenylalanYlvalythreonylleucylglycylaspartylprolylglycylisoleucylglutamylglutaminylsErylleucyllysylisoleucylaspartylthreonylleucylIsoleucylglutamylalanylglycylalanylasparthlalanylleucylglutamylleucylglycylisoleucylprolylphenylalanylseRylaspartylprolylleucylalanylaspartylglycylpRolylthreOnylisoleucylglutaminylasPfraginylalanylthreonylleucylarfinylalanylphenylalanylalanylalanylglycylvalythreonylprolylalanylglutaminylcysteinylphenylalanylglutamylmethionylleucylalanylleuOylisoleucylarginylglutaminyllysyhistidylprolylthreonylisoleucylprolylisoleucylglycylleucylmethionyltyrosylalanylasparaginylleucylvalylphenylalanylasparaginyllysyglycylisoleucylaspartylglutamylphenylalanylthrosylalanylglutaminylcysteinylglutamyllysylvalylglycylvalylaspartylserylvalylleucylvalylalnylaspartylvalylprolylvalylglUtaminylglutamylserylalanylprolylphenylalanylarginylglutaminylalanylalanylleucylarginylhistidylasparaginyvalylalanylprolylisoleucylprolylisoleucylphenylalanylisoleucylphenylalanylisoleucylcysteinylprolylprolylaspartylalanylaspartylaspartylaspartylleucylleucylarginylglutaminylisoleucylalanylseryltyrosylglycylarginylglycyltyrosylthreonyltyrOsylleucylleucylserylarginylalanylglycylvalylthreonylglycylalanylglutamYlasparainylarginylalanylalanylleucylprolylleucylasparaginylhistidylleucylValylalanyllysylleucyllysylglutamyltyrosylasparaginylalanylalanylprolylprolylleucylglutaminylglgycylphenylalanylglycylisoleucylserylalanylprolylaspartylglutaminylvalyllysylalanylalanylisoleucylaspartylalanylglycylalanylalanylglycylalanylisoleucylserylglycylserylalanylisoleucylvalyllysylisoIeucylisoleucylglutamylglutaminylHistidylasparaginyliSoleucylglutamylprolylglutamyllysylmethionylleucylalanylalanylleucyllysylvalylphenylalanylcalylglutaminylprolylmethionlysylalanylalanylthreonylarginylserine

都转化为质数乘机的话,会是相当相当大的一个数啊!所以在算乘积之前把超长单词去掉是个办法:)
renyangok 2008-06-16
对于第二题这种文本处理工作我觉得用shell更容易,一行完事,不用写这么多代码,其实很多语言工具都可以作同样的事,关键是看实际应用中哪个最合适:
cat data.txt | awk '{print $2}' | sed 's/^.\{4\}//g' | sort | uniq -c | sort -r

测试数据:
a 19800120
b 19920106
c 19970120
d 19150106
e 19380120
f 19990101

结果:人数 生日
3 0120
2 0106
1 0101
chinahotdog 2008-05-05

//2.2 求解:有一个文本文件,记录了某个学校所有人的姓名、出生日期(假设没有人重名,该校大约有2万人)。

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;

public class Test1 {
 public static void main(String[] args) {
  //
  int[][] date = new int[12][31];
  int max = 0;
  int month = 0;
  int day = 0;
  int length = 0;
  
  // read file
  try {
   String file = new String("d:\\test\\test.txt");
   BufferedReader bufferedReader =
    new BufferedReader(new InputStreamReader(new FileInputStream(file)));
   String line = bufferedReader.readLine();
   while (line != null) {
    length = line.length();
    month = Integer.parseInt(line.substring(length - 4, length - 2));
    day = Integer.parseInt(line.substring(length - 2, length - 0));
    date[month - 1][day - 1]++;
    line = bufferedReader.readLine();
   }
  } catch (Exception e) {
  }

  // display
  for (int i = 0; i < date.length; i++) {
   for (int j = 0; j < date[i].length; j++) {
    if (date[i][j] > max) {
     max = date[i][j];
     month = i + 1;
     day = j + 1;
    }
   }
  }
  System.out.println("最多人的日期是:" + month + "月" + day + "日");
 }
}

小蛋蛋 2008-04-30
import java.io.*;
public class Main {


String str[]=new String[10];


/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

long begin=System.currentTimeMillis();
System.out.println("请输入你的号码:");
try
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String ss=br.readLine();
if(contains(ss,'0'))
{

}
else if(contains(ss,'1'))
{

}
else
{

Test a=new Test();
Stack s=new Stack();

a.Perm(s, ss, 0);

}
long end=System.currentTimeMillis();
long t=end-begin;
System.out.println("本次使用的时间是: "+t);
}
catch(Exception e)
{
System.out.println(" 00000 "+e.getMessage());
}
}

public static boolean contains(String s,char k)
{
for(int i=0;i<s.length();i++)
{
if(s.charAt(i)==k)
return true;
}
return false;
}




}
小蛋蛋 2008-04-30
public class Test {

String[] str=new String[10];

public Test()
{
str[2]="abc";
str[3]="def";
str[4]="ghi";
str[5]="jkl";
str[6]="mno";
str[7]="pqrs";
str[8]="tuv";
str[9]="wxyz";
}


public void Perm(Stack s,String st,int k)
{
String temp=st.substring(k,k+1);
int num=ToInt(temp);

for(int i=0;i<str[num].length();i++)
{
s.Add(str[num].charAt(i));
if(s.getLength()==st.length())
{
s.print();
}
else
{
Perm(s,st,k+1);
}
s.deleteNode();
}
}

public int ToInt(String s)
{
int i=Integer.parseInt(s);

return i;
}
}
小蛋蛋 2008-04-30
下面是我的程序
写的很不好:

/*
* 实现堆栈类
* 这个堆栈是一个链表形式的表示
* 其中链表的方向是从top指向尾节点
* 我们添加元素和删除元素都是对top节点进行操作的
* 也就是说,top节点就是堆栈的最上面的元素
*/
public class Stack {

/*
* 记录栈顶的元素状态
*/
public StackNode top;

public int len;

/**
* 构造函数
*/
public Stack()
{
top=null;
len=0;
}

/**
* 获得这个堆栈的长度
* @return
*/
public int getLength()
{
return len;
}

/**
* 看堆栈是不是为空
*/
public boolean IsEmpty()
{
return top==null;
}

/**
* 获得栈顶元素单元存放的数据
*/
public char getTop()
{
return top.data;
}

/**
* 在堆栈中新添加一个元素
* @param n
*/
public void Add(char n)
{
StackNode s=new StackNode();
s.data=n;
s.next=top;
top=s;
len++;
}

/**
* 删除堆栈的栈顶元素
*
*/
public char deleteNode()
{
if(IsEmpty())
{
return ' ';
}
else
{
char n=top.data;
top=top.next;
len--;
return n;
}
}

/**
* 输出这个堆栈中存放的字符串内容
*
*/
public void print()
{
StackNode t=top;
String s="";
while(t!=null)
{
s=s+t.data;
t=t.next;
}
s=s.trim();
int a=s.length();
for(int i=a-1;i>=0;i--)
{
System.out.print(s.charAt(i));
}
System.out.println();
}


}

class StackNode
{
public char data;
public StackNode next;

public StackNode()
{
data=' ';
next=null;
}
}
小蛋蛋 2008-04-30
大家好
我是一个大学生
自己做了一下第一个题目
感觉还可以
自己用两种方法做的
一个是建立一棵树,然后对这个树进行深度优先遍历
这样把结果给输出出来

然后另外我又用递归的方法做了一遍
然后输出结果

发觉如果数的位数比较多的话用递归时间比用树的时间要长

例如:
我输入 56232876
用递归的话全部的时间是: 37453
要是用树的话加上生成树和遍历树的过程的话一共用了 26172
是不是一般树比较大的时候就尽量不用递归啊
happynoob 2008-04-25
bookong 写道
那这样不就是相当于
1、取得一个单词
2、全转换成小写
3、排序
4、去掉重复的字符
5、放入HashSet<String>
6、循环1,直到没有新的单词
7、结果在HashSet中迭代



你是rn的那个熊猫吗?
sword_ljx 2008-04-25
问题2:用多线程并发读文件,用一个hashtable存储结果,这样效率能快一些。
myaniu 2008-04-25
对于问题2:

基于效率速度考虑。
从io缓存,cpu的缓存,以及cpu的流水处理方式考虑。

以下方式或许更更好的利用现代CPU的优势:

使用 1231 + 1大小的数组。days[1232]
1.整个读入所有记录。
2.数组初始化为0
3.挨个将月日转化成数字 n,然后days[n]++
4.遍历数组,找出最大值
bookong 2008-04-25
那这样不就是相当于
1、取得一个单词
2、全转换成小写
3、排序
4、去掉重复的字符
5、放入HashSet<String>
6、循环1,直到没有新的单词
7、结果在HashSet中迭代
bookong 2008-04-25
GreenForest 写道
253620236 写道
昨天的JAVA面试题,感觉挺难大家帮忙看看!新手第一次发帖!
2.3求解:在一份文本文件中,查找其中所有的anagram。例如,如果这份文件中包含了stop、tops、pots这样三个单词,这三个词就是一组anagram,这三个单词都是由s、t、o、p这四个字母组成的。这份文件中可能存在多组anagram,大小写视为同样字符。在解答时,需要注意代码的效率、质量。当不能给出完整代码时,可以描述解题思路。

按我的理解,字母相同(不分大小写)且各字母个数也相同的单词,就是一组anagram,比如说abcd和bcda也算是一组anagram,而不是单指stop、tops和pots这三个单词。
我这样理解错了么?怎么很多人都认为只有stop、tops和pots这三个单词才算是一组anagram。


我觉得你说的是对的。这道题要的结果应该不是 stop,tops,pots...而应该是类似 stop,list,img...因为它说“查找其中所有的anagram”而不是“某个anagram对应的所有单词”
GreenForest 2008-04-25
253620236 写道
昨天的JAVA面试题,感觉挺难大家帮忙看看!新手第一次发帖!
2.3求解:在一份文本文件中,查找其中所有的anagram。例如,如果这份文件中包含了stop、tops、pots这样三个单词,这三个词就是一组anagram,这三个单词都是由s、t、o、p这四个字母组成的。这份文件中可能存在多组anagram,大小写视为同样字符。在解答时,需要注意代码的效率、质量。当不能给出完整代码时,可以描述解题思路。

按我的理解,字母相同(不分大小写)且各字母个数也相同的单词,就是一组anagram,比如说abcd和bcda也算是一组anagram,而不是单指stop、tops和pots这三个单词。
我这样理解错了么?怎么很多人都认为只有stop、tops和pots这三个单词才算是一组anagram。
阳光晒晒 2008-04-25


import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 * 2.3求解:在一份文本文件中,查找其中所有的anagram。
 * 例如,如果这份文件中包含了stop、tops、pots这样三个单词,
 * 这三个词就是一组 anagram,
 * 这三个单词都是由s、t、o、p这四个字母组成的。
 * 这份文件中可能存在多组anagram,大小写视为同样字符。
 * 在解答时,需要注意代码的效率、质量。当不能给出完整代码时,
 * 可以描述解题思路。
 * @author maodajun327
 *
 */
public class AnagramWords {
		Map map= new HashMap();
		String[] strArray = new String[]{  
		            "stop","tops","pots"
		         };  
		public static void main(String arg[]){
			AnagramWords D2 = new AnagramWords();
			for(int i = 0 ; i < D2.strArray.length ; i++ ){
				D2.getTheWord(D2.strArray[i]);
			}
			List list  = D2.flashMap();
			System.out.println(list);
			
		}
		public void getTheWord(String str){
			str= str.toLowerCase();
			char[] arr=str.toCharArray();
			Arrays.sort(arr);
			String key =String.valueOf(arr);
			if(arr.length<=2){//字数为2当然不用了。
				return;
			}
			if(map.get(key)==null){
				Set set = new TreeSet();
				set.add(str);
				map.put(key, set);		
			}else{
				Set set = (Set) map.get(key);
				if(!set.contains(str)){//重的不要
					set.add(str);
				}
			}
			
		}
		public List flashMap(){
			List list = new ArrayList();
			Set set= map.entrySet();
			Iterator<Map.Entry> it=set.iterator();
			while(it.hasNext()){
				Map.Entry<String, Set> tmp= it.next();
				if(tmp.getValue().size()>=3){//小于3的不要。
					list.add(tmp.getValue());
				}
			}
			return list;			
		}
	
}

yujianqiu 2008-04-25
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class PhoneNumber {

	private Map<Character, char[]> keymap;

	@Before
	public void setUp() throws Exception {
		keymap = new HashMap<Character, char[]>(10);
		keymap.put('0', new char[] { '0' });
		keymap.put('1', new char[] { '0' });
		keymap.put('2', new char[] { 'a', 'b', 'c' });
		keymap.put('3', new char[] { 'd', 'e', 'f' });
		keymap.put('4', new char[] { 'g', 'h', 'i' });
		keymap.put('5', new char[] { 'j', 'k', 'l' });
		keymap.put('6', new char[] { 'm', 'n', 'o' });
		keymap.put('7', new char[] { 'p', 'q', 'r', 's' });
		keymap.put('8', new char[] { 't', 'u', 'v' });
		keymap.put('9', new char[] { 'w', 'x', 'y', 'z' });
	}

	@After
	public void tearDown() throws Exception {
	}

	@Test
	public void testCheckNumber() {
		String number = "137689563";
		try {
			checkNumber(number);
		} catch (IllegalArgumentException e) {
			Assert.fail(e.getMessage());
		}
		number = "133";
		try {
			checkNumber(number);
		} catch (IllegalArgumentException e) {
			Assert.fail("Equals 3");
		}
		number = "13312341234";
		try {
			checkNumber(number);
		} catch (IllegalArgumentException e) {
			Assert.fail("Equals 11");
		}
		number = "13";
		try {
			checkNumber(number);
			Assert.fail("Shorter then 3");
		} catch (IllegalArgumentException e) {
		}
		number = "1376118956312";
		try {
			checkNumber(number);
			Assert.fail("Longer then 11");
		} catch (IllegalArgumentException e) {
		}
		number = "13761189B5";
		try {
			checkNumber(number);
			Assert.fail("Invalid char.");
		} catch (IllegalArgumentException e) {
		}
	}

	@Test
	public void testEnumerate() {
		String number = "65967427";
		Set<String> enums = enumerate(number);
		for (String element : enums) {
			System.out.println(element);
		}
		System.out.println("Total: " + enums.size());
	}

	/**
	 * @param number
	 */
	private void checkNumber(String number) {
		if (!number.matches("[0-9]{3,11}")) {
			throw new IllegalArgumentException("Invalid phone number.");
		}
	}

	private Set<String> enumerate(Set<String> base, char[] chars) {
		Set<String> result = new TreeSet<String>();
		if (base.isEmpty()) {
			for (char element : chars) {
				String s = new String(new char[] { element });
				result.add(s);
			}
		} else {
			for (String baseString : base) {
				for (char element : chars) {
					result.add(baseString + element);
				}
			}
		}
		return result;
	}

	/**
	 * @param number
	 * @return
	 */
	private Set<String> enumerate(String number) {
		checkNumber(number);
		char[] chars = number.toCharArray();
		Set<String> result = new HashSet<String>();
		for (char element : chars) {
			result = enumerate(result, keymap.get(element));
		}
		return result;
	}

}


这个比较有趣,写一个看看我家电话号码值钱不。
aniude 2008-04-25
第一题应该不难吧
第二题可以用list 和 set ,然后把set的东西再遍历一下?
第三题可以用正则的话应该不难吧
GreenForest 2008-04-23
Joo 写道
manbearpig1 写道
第三题,26个字母对应2开始的26个质数,对每个词求乘积,结果一样的认为是等价的
前提:不考虑乘法溢出,复杂度上界O(line_of_file * max_word_len)


这个很不错.但问题是每个字母都要转换一边是否高效?
数字不会很大怎么会溢出的?

呵呵,这么一说倒是想起来了,如果再在题目上加上对于空间或者时间的要求,可能就更难一层了
忘记曾经是哪个公司的题目中作此要求


发生溢出的可能性还是很小的,毕竟很少会有很长的单词。
我觉得问题是乘积的结果会很大,最小的8个质数的乘积为9699690。
leon_a 2008-04-23
metaphy 写道
GreenForest 写道
第2题

1、int birthday[12][31]。
2、将数组中所有元素初始化为0。
3、循环遍历所有人,如果当前人n月m日生日,则birthday[n-1][m-1]++。
4、找出数组中最大的值。


这个应该是最省空间和最快的,这个比定义arr[1231]大小的数组要机智的多;其次应该是用HashMap来做


拿空间换时间,主意不错。
leon_a 2008-04-23
sqhe18 写道
7thbyte 写道
nmvr2600 写道
第一个题和论坛ruby版里那个“容易记的电话号码”有些类似
第二个,就是统计生日最多的哪一天,但是生日里面的年可以直接忽略掉,需要的就只有月日。月和日不要一起统计,先算月。先把生日最多的那个月份找到,再去统去到底是哪一天。呵呵,这样最后需要计算个数的人就少了很多了吧。直接去算每天出现的人数还是有点笨。如果数据量再多的话,可以借用下数理统计的知识。
第三个,使用正则表达式\b(?i)[s|t|o|p]{4}\b,搞定~~


“先把生日最多的那个月份找到”的时候,怎么都得遍历一次吧。。
再统计天的话,又部分遍历一次。。哪里减小了运算量啊。。

把月和日当成一个整体作为key,遍历一次就可以了。。

这个正则表达式可以吗。。似乎"tttt"这种字符串也能匹配上


把月和日当成一个整体作为key的话,需要遍历365个元素。
而将月和日分开的话,只需要遍历12+31个元素。
但是后一种方法需要同时在两个collection里插入,可能有点得不尝失


这么算不对的哦,比如有30个人是3月1~30号出生的
另外有20个人是2月10号出生
Joo 2008-04-23
GreenForest 写道
第3题

设times= 26;

a 为 0*times + 0;
b 为 1*times + 1;
c 为 2*times + 2;
d 为 3*times + 3;
.
.
.
z 为 26*times + 26;

对于一个单词,如stop,它的值为s+t+o+p

根据需要调整times的大小。
当times>26的时候,冲突的情况应该很少了。

这个方法前面有兄弟提到过类似的,不过是把字母对应承相应的2以上的质数
发表评论

提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则

您还没有登录,请登录后发表评论

253620236
搜索本博客
博客分类
最近加入圈子
最新评论