1、哈希
关于HashMap的东东真是比较多,找了STL源码看,那东西真不是菜鸟看的,还是看Java的吧,比较好的有这个
http://uuubd.iteye.com/blog/1447129,其实这个数组和链表的图很不错,非常形象,另外一个http://www.iteye.com/topic/539465的图也很不错
为什么是看HashMap,不是看HashSet什么的,因为HashSet也是用HashMap去生成,还真是省力。
为什么要用hash?
数组查找快,直接索引搞定,增加和删除太慢,移动大块内容;链表增加删除倒是快, 查找太慢,一个个next。于是组合这俩就成了最简单的hash。当然,Java的hashMap也是这么干的
Hash怎么增加的可以参考http://uuubd.iteye.com/blog/1447129,算出hash值了,同一个hash值下维持一个链表,直接将新值增加到链表头;删除会比较麻烦一点,找到hash值后,遍历链表,删。
如果这个位置有个1个元素,需要像数组一样移动元素么?看源码是不需要的,就放个空链表,下次来了再增加即可,有点空间换时间的感觉,其实蛮像桶的,给你设置好固定个数的桶,然后来了往里放,唯一不同的是hashMap的桶可能需要resize();
这2个都是对HashMap源码很生动到位的解释
为什么要看hash?常遇到的面试题呢?参考http://blog.youkuaiyun.com/v_JULY_v/article/details/6256463
8-12补充,map怎么保证key唯一呢?查了HashMap找不到,找Map,貌似是有个
public abstract Set keySet();
保存key值,用set的唯一性,那set怎么保证呢?查到HashSet,太坑爹了,用HashMap的key唯一来保证。TreeSet也是用TreeMap,坑爹啊。CopyOnWriteArraySet不是那么坑,不过用个list来存,每次遍历,写equals方法,好像是麻烦了点。查了下,Set中实现元素互异的各种方法差异很大,大致可以分为三种:使用equals,使用hashCode,使用compareTo。如果用hash,只要保证hash没有冲突,肯定是最高效的,看起来这个疑问解决了
2、字符串
1)设计算法判断字符串中的字符都是唯一的,如果不适用额外的数据结构呢?
正常情况考虑(除开编码因素),字符只有不到256个,可以考虑用hash的思想,建一个最大256的int数组,遍历字符串中字符,取得ascii码,映射到数组中,如果原来为0,则加1,如果已经为1,则知道有重复的;其实只是0、1的测试,甚至可以用bit搞定,test(i)为true,则返回有相同元素
2)实现常见的c风格的字符串反转
void reverse(char *str)
{
char *end = str;
while (*end)
{
end++;
}
end--;
while (str < end)
{
char temp = *str;
*str++ = *end;
*end-- = temp;
}
}
3)设计一个算法移除字符串中的重复字符,算法不使用额外缓冲。并对算法设计测试用例
如果用额外缓冲,最简单的写法就是申请set,直接一次扫描,add即可,现在项目中就是这样干,只是效率不一定高(set怎么保证唯一性呢?用map的key唯一性,map里key的唯一性又怎么保证呢?回头找找)
不使用额外缓冲,稍微麻烦点,对每个元素都要扫描后面有没有相同的,有则跳过,没有则存下,而且src和des是同一块内存区,幸好是高位往低位存,不然麻烦,时间复杂度就是O(n^2)了,跟冒泡的比较差不多(感觉,不能光说思路,写代码也一次写对其实还是蛮难的,得练练)
cracking给的解法是扫描已有的,进行比较,效率应该是差不多。停止条件都是遇到一样的跳出,不同的是结果中,第一种是取相同字符的最后一个进行存,第二个是取相同字符的第一个遇到的进行存
4)写一个函数判断两个字符串是否使用相同的字符构成
这边需要注意的是,字符串如果只是字母的话,可以用52的数组,映射过去,可以参考http://blog.youkuaiyun.com/v_JULY_v/article/details/6347454解法;另外,如果要代码写起来方便的话,2行搞定,调用STL的sort函数
int isEqualStr(string left, string right)
{
sort(left.begin(),left.end());
sort(right.begin(), right.end());
return strcmp(left.c_str(), right.c_str());
}
5)编写代码将字符串在中的空格替换为‘%20’
6)给出一张图片,表示为NXN的居然,每个像素点为4字节。写一个函数实现将这张图片旋转90°。
7)实现算法:在一个MxN的矩阵中,如果某一元素为0,则将其所在的行和列都置为零。
8)假设你已经有一个函数用来 isSubstring(s1,s2) 用来判断字符串s1是否是字符串s2的子串。那么现在给你一个字符串s1和s2,让你判断s1是否是s2循环位移得到的。你的算法中只能调用一次isSubstring (比如“waterbottle”循环位移就可以得到"erbottlewat")。