这是一个我刚刚毕业时候面试腾讯的面试题,当时我的答案是先排序,然后取中间的数,那么该数就是我们需要的数,但是,这种方法的复杂度不是线性的,所以说就被out了。从那之后,我一直在思考这个问题该如何被线性解决。慢慢地有一个想法,就是制作表,表的大小就是L* 2 (L是数组的长度)。表的每一行第一个元素是数组中的数字,第二个元素是该数字出现的次数。但是,接着想下去,就发现其实在loop数组的同时,我们需要loop该表,因为当我们loop到数组某一元素时,我们要找到表中该数字的出现的次数,然后加一。于是,复杂度一下子就上去了,然后一直被block住。然后竟然没有百度,罪过呀 ^.^ ^.^ ^.^
前几天和一个朋友吃饭聊到这个题目,他说可以根据“出现次数超过一半”这个特性去解题。如果我们同时移除两个不同的数,那么剩下的数中,该数在剩下的数中出现的次数也是超过一半。 这样的话,我们可以按照这个思路做下去,唯一的问题是,如果一个数连续出现很多次,我们该如何去做移除两个不同的数这个动作。 我们可以用一个count来记录,如果出现多次,我们就把它加1,不同的数就减一。代码如下:
if (inPtr == NULL && len <= 0)
return -1;
int i, result;
int count = 0;
if (count==0){
result = inPtr[i];
count = 1;
}else{
if(result == inPtr[i])
count++;
else
count--;
}
}
}
int main(){
int a[10] = {1,4,2,5,4,3,4,4,2,4};
int target_data;
target_data = half_search(a,10);
return 0;
}
根据key,计算出key对应记录的储存位置
position = f(key)
函数f就是hash函数
[2]hash冲突定义
不同的key可能得到相同的position。原因为key值的范围过大。如int.
如果构造一个完全没有冲突的表。那么对应的地址空间就是4G,这是根本不
实现的。为了处理这个问题。就允许不同的key可以有相同的position。
[3]hash表定义
映射的集合
[4]设计一个好的hash函数非常重要
由[2]可知,一个好的hash函数可以使positions集中分布在某一段内存地址范围内。
并且position在这段地址范围内存尽量均匀。这样每个key对应的position就尽可能
少了,即hash冲突少。查找就会快一点。
[5]所谓的hash桶定义
就是预分配的一段连续的储存空间
[6]处理冲突的方法
(1)开放定址法:就是先指定一个桶,然后position = f(key,d),如果postion已经存在了,改变参数d,
继续计算position = f(key,d),直到postion不存在
d的不同取值的算法有:线性探测再散列,二次探测再散列,伪随机探测再散列。
听这名字觉得好高深哦。实际上, 就是为了更高效地计算出没有使用的position
(2)链地址法
就是把position相同的item按插入的先后顺序组成一个链表
#include <stdio.h>
#include <string.h>
#define HASHSIZE 10
int hash_function(int key);
typedef struct LINE_NODE{
int key;
int value;
struct LINE_NODE *next_node; // used to solve collision
}node;
node hashtable[HASHSIZE];
int hash_function(int key){
int table_idx;
table_idx = key % 4; // A simple hash rule
return table_idx;
}
int main(){
int i;
int table_idx;
int a[10] = {1, 4, 2, 4, 4, 3, 5, 4, 4, 4};
memset(hashtable, 0x0, HASHSIZE * sizeof(node));
for(i=0;i<10;i++){
table_idx = hash_function(a[i]);
if (hashtable[table_idx].key == a[i])
{
hashtable[table_idx].value++;
}else {
if (hashtable[table_idx].value == 0)
{
hashtable[table_idx].key = a[i];
hashtable[table_idx].value++;
}else {
hashtable[table_idx].next_node = &hashtable[HASHSIZE-1]; // simple allocation.
hashtable[table_idx].next_node->key = a[i];
hashtable[table_idx].next_node->value++;
}
}
printf("i: %d, a[i]: %d, hashtable[%d].key: %d. \n",i, a[i], table_idx, hashtable[table_idx].key);
}
for (i=0;i<10;i++){
printf("key: %d, value: %d. \n",hashtable[i].key, hashtable[i].value);
}
return 0;
}