一道公司的笔试题

a707000646 2015-03-30 08:16:23
宠物有六个属性 如 1,3,2,4,5,6当改变顺序与另一只相同时则视为相同 如123456 县有n组数据 输出1对相同的宠物,如果有多个相同的,则任意输出其中的两个
如有输入
{
{1, 2, 3, 4, 5, 6},
{1,6,2,5,4,3},
{2,3,4,5,6,7}
}
输出{1, 2, 3, 4, 5, 6},{1,6,2,5,4,3},要求尽量快,
...全文
1633 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
petermjx3001 2016-02-17
  • 打赏
  • 举报
回复
引用 20 楼 u012511611 的回复:
如果有各种int属性。那么最好存储为bit形式,比如123456,就是01111110,比如234567,就是11111100。省去了排序的麻烦。 重头到尾扫描一遍。 如果不能存储为这种形式,就要有排序模板。这样,每次有新的的宠物,就可以直接产生全排序。比如 int * p6(int a[])//input pet with Permutation . { int *p[6][6]; ........ return p; } int **k[]; for(int i=0;i<n;i++) { if(k[i]==null) k=p(i.[1,2,3,4,5,6]);//if null for(int i=0;i<k.length;i++)if(find successful) return ;//if find return. k=p(i.[1,2,3,4,5,6]);//add new to templete }
同20楼的方法,把每位的数字作为1位移的数量,例如如果是3,就为1<<3,然后把所有的位移之后的数进行累加和,得到数SUM,SUM相同的数即是数组元素相同的。
小程真伟大 2015-12-13
  • 打赏
  • 举报
回复
如果有各种int属性。那么最好存储为bit形式,比如123456,就是01111110,比如234567,就是11111100。省去了排序的麻烦。 重头到尾扫描一遍。 如果不能存储为这种形式,就要有排序模板。这样,每次有新的的宠物,就可以直接产生全排序。比如 int * p6(int a[])//input pet with Permutation . { int *p[6][6]; ........ return p; } int **k[]; for(int i=0;i<n;i++) { if(k[i]==null) k=p(i.[1,2,3,4,5,6]);//if null for(int i=0;i<k.length;i++)if(find successful) return ;//if find return. k=p(i.[1,2,3,4,5,6]);//add new to templete }
zhouxiaofeng1021 2015-12-02
  • 打赏
  • 举报
回复
{ {1, 2, 3, 4, 5, 6}, {1,6,2,5,4,3}, {2,3,4,5,6,7} } 排序 { {1, 2, 3, 4, 5, 6}, {1,2,3,4,5,6}, {2,3,4,5,6,7} } 转化 { 123456, 123456, 234567 } 然后就是找到两个相同的6位数 哈希一下就可以吧 整体时间O(N) 空间O(N)
Yofoo 2015-09-14
  • 打赏
  • 举报
回复
hash = (a1+a2+...+an)^(a1^a2^...^an)
lidowx 2015-09-11
  • 打赏
  • 举报
回复

bool Find(std::vector<std::vector<int>> & in,std::vector<int> & out1,std::vector<int> & out2) {
	unsigned int flag[64];
	memset(flag,0,sizeof(flag));
	out1.clear();
	out2.clear();

	for ( int i=0;i<in.size();++i ) {
		unsigned char n = 0;
		unsigned int sn = 0; 
		std::vector<int> & v = in[i];
		for ( int j=0;j<v.size();++j ) {
			n += (0x01<<(v[j]-1));
			sn *= 10;
			sn += v[j];
		}
		if ( 0!=flag[n] ) {
			unsigned int s = flag[n];
			while( s>0 ) {
				out1.insert(out1.begin(),s%10);
				s /= 10;
			}
			out2 = v;
			return true;
		}
		flag[n] = sn;
	}
	return false;
}
未狂 2015-08-27
  • 打赏
  • 举报
回复
set或map,往里插入,红黑树自动排序了
cnmhx 2015-07-11
  • 打赏
  • 举报
回复
先将每个宠物的属性按字母升序方式写为一个单词。 对单词排序即可。
hxh_2014 2015-07-09
  • 打赏
  • 举报
回复
不是和相等,积相等就行吗?
一根烂笔头 2015-04-18
  • 打赏
  • 举报
回复
引用 12 楼 micropentium6 的回复:
[quote=引用 11 楼 my_live_123 的回复:] [quote=引用 10 楼 micropentium6 的回复:] 你都写到这个地步了,楼主只要求找到任意两对。那何苦还等到全部位运算完成再做查找? 每一个位运算完成,直接hash, 如果有collision,判断xor是否为0,如果true, 打完收工! 其实,当我看到有且只有6个不重复数字,第一反应是用regular expression! [quote=引用 9 楼 my_live_123 的回复:]

#include <stdio.h>
#include <stdlib.h> 

/*简化问题:假设m * n中矩阵元素非负,同行元素互不相等且最大值不超过32
  将元素值视为二进制中为1的位数,如此将集合元素映射到一个数值,而不用
  关心元素的顺序,处理映射后的值,问题转变为数组中寻找相同的元素
  */

#define DEM 6
int equal_set(int (*data)[DEM], int m, int n)
{
	unsigned int map[m];
	int i, j;

	if(!data || m < 0 || n < 0)
		return -1;

	//映射
	for(i = 0; i < m; ++i) {
		map[i] = 0;
		for(j = 0; j < n; ++j) { //将集合映射到数值
			map[i] = map[i] | 1 << data[i][j];
		}
	}

#if 1
	int nr;
	//检索相等元素
	for(i = 0; i < m; ++i) {
		nr = 0;
		for(j = i + 1; j < m; ++j) {
			if(map[j] && (map[i] ^ map[j]) == 0) { //相同
				printf("%d ", j);
				map[j] = 0; //清空,避免相等元素重复输出
				++nr; //计数
			}
		}
		if(nr)
			printf("%d ; sum : %d\n", i, ++nr);
	}
#else
	//上面检索相对慢些,可以考虑使用hash,提高速度

#endif
	return 0;
}

void test(void)
{
	int data[DEM][DEM] = {
		1,2,3,4,5,6,
		1,3,2,4,6,5,
		3,5,1,4,6,2,

		1,7,2,4,6,5,
		1,2,7,4,5,6,

		1,3,4,2,6,5,
	};
	equal_set(data, DEM, DEM);
}

int main(int argc, char *argv[])
{
	test();
	exit(0);
}
抛砖引玉
[/quote] 恩,是个优化的方案!不过,开篇注释我说明了,我把楼主的问题,抽象成了一般问题!代码中我也提到了hash作为后续优化选择! 正则表达式如何做?请指教[/quote] 你太客气了!我指教不了你,我是来补习算法的! 你们c++版的那个什么老鼠最近不出来了啊?弄的我都木有乐子看了! 正则是玩笑的说法,水园浑多了。你写个[1-6]{6},然后揍交给正则去找pattern吧!这样你的代码揍是O(n^2)的复杂度啦!java程序员写算法最爱肿么干![/quote]
  • 打赏
  • 举报
回复
引用 11 楼 my_live_123 的回复:
[quote=引用 10 楼 micropentium6 的回复:] 你都写到这个地步了,楼主只要求找到任意两对。那何苦还等到全部位运算完成再做查找? 每一个位运算完成,直接hash, 如果有collision,判断xor是否为0,如果true, 打完收工! 其实,当我看到有且只有6个不重复数字,第一反应是用regular expression! [quote=引用 9 楼 my_live_123 的回复:]

#include <stdio.h>
#include <stdlib.h> 

/*简化问题:假设m * n中矩阵元素非负,同行元素互不相等且最大值不超过32
  将元素值视为二进制中为1的位数,如此将集合元素映射到一个数值,而不用
  关心元素的顺序,处理映射后的值,问题转变为数组中寻找相同的元素
  */

#define DEM 6
int equal_set(int (*data)[DEM], int m, int n)
{
	unsigned int map[m];
	int i, j;

	if(!data || m < 0 || n < 0)
		return -1;

	//映射
	for(i = 0; i < m; ++i) {
		map[i] = 0;
		for(j = 0; j < n; ++j) { //将集合映射到数值
			map[i] = map[i] | 1 << data[i][j];
		}
	}

#if 1
	int nr;
	//检索相等元素
	for(i = 0; i < m; ++i) {
		nr = 0;
		for(j = i + 1; j < m; ++j) {
			if(map[j] && (map[i] ^ map[j]) == 0) { //相同
				printf("%d ", j);
				map[j] = 0; //清空,避免相等元素重复输出
				++nr; //计数
			}
		}
		if(nr)
			printf("%d ; sum : %d\n", i, ++nr);
	}
#else
	//上面检索相对慢些,可以考虑使用hash,提高速度

#endif
	return 0;
}

void test(void)
{
	int data[DEM][DEM] = {
		1,2,3,4,5,6,
		1,3,2,4,6,5,
		3,5,1,4,6,2,

		1,7,2,4,6,5,
		1,2,7,4,5,6,

		1,3,4,2,6,5,
	};
	equal_set(data, DEM, DEM);
}

int main(int argc, char *argv[])
{
	test();
	exit(0);
}
抛砖引玉
[/quote] 恩,是个优化的方案!不过,开篇注释我说明了,我把楼主的问题,抽象成了一般问题!代码中我也提到了hash作为后续优化选择! 正则表达式如何做?请指教[/quote] 你太客气了!我指教不了你,我是来补习算法的! 你们c++版的那个什么老鼠最近不出来了啊?弄的我都木有乐子看了! 正则是玩笑的说法,水园浑多了。你写个[1-6]{6},然后揍交给正则去找pattern吧!这样你的代码揍是O(n^2)的复杂度啦!java程序员写算法最爱肿么干!
一根烂笔头 2015-04-18
  • 打赏
  • 举报
回复
引用 10 楼 micropentium6 的回复:
你都写到这个地步了,楼主只要求找到任意两对。那何苦还等到全部位运算完成再做查找? 每一个位运算完成,直接hash, 如果有collision,判断xor是否为0,如果true, 打完收工! 其实,当我看到有且只有6个不重复数字,第一反应是用regular expression! [quote=引用 9 楼 my_live_123 的回复:]

#include <stdio.h>
#include <stdlib.h> 

/*简化问题:假设m * n中矩阵元素非负,同行元素互不相等且最大值不超过32
  将元素值视为二进制中为1的位数,如此将集合元素映射到一个数值,而不用
  关心元素的顺序,处理映射后的值,问题转变为数组中寻找相同的元素
  */

#define DEM 6
int equal_set(int (*data)[DEM], int m, int n)
{
	unsigned int map[m];
	int i, j;

	if(!data || m < 0 || n < 0)
		return -1;

	//映射
	for(i = 0; i < m; ++i) {
		map[i] = 0;
		for(j = 0; j < n; ++j) { //将集合映射到数值
			map[i] = map[i] | 1 << data[i][j];
		}
	}

#if 1
	int nr;
	//检索相等元素
	for(i = 0; i < m; ++i) {
		nr = 0;
		for(j = i + 1; j < m; ++j) {
			if(map[j] && (map[i] ^ map[j]) == 0) { //相同
				printf("%d ", j);
				map[j] = 0; //清空,避免相等元素重复输出
				++nr; //计数
			}
		}
		if(nr)
			printf("%d ; sum : %d\n", i, ++nr);
	}
#else
	//上面检索相对慢些,可以考虑使用hash,提高速度

#endif
	return 0;
}

void test(void)
{
	int data[DEM][DEM] = {
		1,2,3,4,5,6,
		1,3,2,4,6,5,
		3,5,1,4,6,2,

		1,7,2,4,6,5,
		1,2,7,4,5,6,

		1,3,4,2,6,5,
	};
	equal_set(data, DEM, DEM);
}

int main(int argc, char *argv[])
{
	test();
	exit(0);
}
抛砖引玉
[/quote] 恩,是个优化的方案!不过,开篇注释我说明了,我把楼主的问题,抽象成了一般问题!代码中我也提到了hash作为后续优化选择! 正则表达式如何做?请指教
  • 打赏
  • 举报
回复
你都写到这个地步了,楼主只要求找到任意两对。那何苦还等到全部位运算完成再做查找? 每一个位运算完成,直接hash, 如果有collision,判断xor是否为0,如果true, 打完收工! 其实,当我看到有且只有6个不重复数字,第一反应是用regular expression!
引用 9 楼 my_live_123 的回复:

#include <stdio.h>
#include <stdlib.h> 

/*简化问题:假设m * n中矩阵元素非负,同行元素互不相等且最大值不超过32
  将元素值视为二进制中为1的位数,如此将集合元素映射到一个数值,而不用
  关心元素的顺序,处理映射后的值,问题转变为数组中寻找相同的元素
  */

#define DEM 6
int equal_set(int (*data)[DEM], int m, int n)
{
	unsigned int map[m];
	int i, j;

	if(!data || m < 0 || n < 0)
		return -1;

	//映射
	for(i = 0; i < m; ++i) {
		map[i] = 0;
		for(j = 0; j < n; ++j) { //将集合映射到数值
			map[i] = map[i] | 1 << data[i][j];
		}
	}

#if 1
	int nr;
	//检索相等元素
	for(i = 0; i < m; ++i) {
		nr = 0;
		for(j = i + 1; j < m; ++j) {
			if(map[j] && (map[i] ^ map[j]) == 0) { //相同
				printf("%d ", j);
				map[j] = 0; //清空,避免相等元素重复输出
				++nr; //计数
			}
		}
		if(nr)
			printf("%d ; sum : %d\n", i, ++nr);
	}
#else
	//上面检索相对慢些,可以考虑使用hash,提高速度

#endif
	return 0;
}

void test(void)
{
	int data[DEM][DEM] = {
		1,2,3,4,5,6,
		1,3,2,4,6,5,
		3,5,1,4,6,2,

		1,7,2,4,6,5,
		1,2,7,4,5,6,

		1,3,4,2,6,5,
	};
	equal_set(data, DEM, DEM);
}

int main(int argc, char *argv[])
{
	test();
	exit(0);
}
抛砖引玉
一根烂笔头 2015-04-15
  • 打赏
  • 举报
回复

#include <stdio.h>
#include <stdlib.h> 

/*简化问题:假设m * n中矩阵元素非负,同行元素互不相等且最大值不超过32
  将元素值视为二进制中为1的位数,如此将集合元素映射到一个数值,而不用
  关心元素的顺序,处理映射后的值,问题转变为数组中寻找相同的元素
  */

#define DEM 6
int equal_set(int (*data)[DEM], int m, int n)
{
	unsigned int map[m];
	int i, j;

	if(!data || m < 0 || n < 0)
		return -1;

	//映射
	for(i = 0; i < m; ++i) {
		map[i] = 0;
		for(j = 0; j < n; ++j) { //将集合映射到数值
			map[i] = map[i] | 1 << data[i][j];
		}
	}

#if 1
	int nr;
	//检索相等元素
	for(i = 0; i < m; ++i) {
		nr = 0;
		for(j = i + 1; j < m; ++j) {
			if(map[j] && (map[i] ^ map[j]) == 0) { //相同
				printf("%d ", j);
				map[j] = 0; //清空,避免相等元素重复输出
				++nr; //计数
			}
		}
		if(nr)
			printf("%d ; sum : %d\n", i, ++nr);
	}
#else
	//上面检索相对慢些,可以考虑使用hash,提高速度

#endif
	return 0;
}

void test(void)
{
	int data[DEM][DEM] = {
		1,2,3,4,5,6,
		1,3,2,4,6,5,
		3,5,1,4,6,2,

		1,7,2,4,6,5,
		1,2,7,4,5,6,

		1,3,4,2,6,5,
	};
	equal_set(data, DEM, DEM);
}

int main(int argc, char *argv[])
{
	test();
	exit(0);
}
抛砖引玉
qjgdftxmu 2015-04-15
  • 打赏
  • 举报
回复
引用 2 楼 a707000646 的回复:
我有一种方法是哈希 但是我不知道 hash_value(int arr[6]) 要怎么写
把int arr[6]换成vector<int>
cnmhx 2015-04-08
  • 打赏
  • 举报
回复
定义等价类:6个属性只要相同(不计次序)就作为一类。 将属性值按大小排列后得到此等价类的唯一标识符,亦可转化为字符串或着整数。 余下的事就是扫描,判断两个标识符是否一致了。
skillart 2015-04-08
  • 打赏
  • 举报
回复
转成字符串,对字符串排序,sum做元素的和,存map。 map<str1,sum1> map<str2,sum2> map<str3,sum3> map<str4,sum4> map<str5,sum5> map<str6,sum6> ... 比如sum1。找到和sum1相等的sum,中间隔断的不比较。比如sum1 = sum2 = sum3 != sum4 !=sum5 = sum6; 只比较sum1,sum2,sum3对应的str,不比较sum6. 也就是比较str1,str2,str3。 同样比较的时候隔断的不用在比较.比如str1 != str2 跳出不用再比较str1跟str3的关系。 不知道这样会不会快些。
super_miker 2015-04-07
  • 打赏
  • 举报
回复
属性的数值范围有没有规定?
kernelkoder 2015-04-07
  • 打赏
  • 举报
回复
现在的公司真会想花招
yubinyuleo 2015-04-04
  • 打赏
  • 举报
回复
如果要快就素数相乘,但是要是会溢出就没办法了
a707000646 2015-03-30
  • 打赏
  • 举报
回复
我有一种方法是哈希 但是我不知道 hash_value(int arr[6]) 要怎么写
加载更多回复(1)

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧