1、提供单词和词典,找到该单词的所有变位词,可以事先花时间和空间处理下该词典。
因为要查找变位词,事先遍历词典,得到每个单词签名,并建立签名列表,签名列表的每个项包含了该签名的所有单词。有了这个列表,直接得到提供单词的签名去遍历签名列表就能找到所有变位词。
2、给定一个4300000000个32位整数的顺序文件,请问你如何可以找到一个至少出现两次的整数
因为2^32>4300000000所以肯定存在至少出现两次的整数
而且是顺序文件,更提醒我们要用二分查找法
1、把所有整数(N个)看成二进制表示法,将第一位bit为1的数目和第一位bit为0的比较,必有一个数目大于等于另一个。
2、在数目大的那堆数字中继续比较第二bit位,按照1的方法比较,以此类推最后能得到重复出现的数字。
同样的道理,假设我们有N个顺序数字他们都在[1,2^n]范围,且N<2^n,如何找到至少一个没有出现的数字,思路和刚刚的一样
1、把所有整数(N个)看成二进制表示法,将第一位bit为1的数目和第一位bit为0的比较,必有一个数目小于等于另一个。
2、在数目小的那堆数字中继续比较第二bit位,按照1的方法比较,以此类推最后能得到没有出现的数字。
#include <stdio.h> #include <stdlib.h> int getRepeat(unsigned char *a, int length, int bitlen) { unsigned char result = 0; int start = 0; for(int i = 1; i <= bitlen; i++) { int bit0 = 0; int bit1 = 0; int mod = 1 << (bitlen - i); int len = length/(1<<(i-1)); for(int j = start; j < start + len; j++) { if((a[j] & mod) == 0) { bit0++; } else { bit1++; } } if(bit0 > bit1) { result |= 0<<(bitlen - i); } else { result |= 1<<(bitlen - i); start+=len/2; } } return result; } int getLost(unsigned char *a, int length, int bitlen) { unsigned char result = 0; int start = 0; for(int i = 1; i <= bitlen; i++) { int bit0 = 0; int bit1 = 0; int mod = 1 << (bitlen - i); int len = length/(1<<(i-1)); for(int j = start; j < start + len; j++) { if((a[j] & mod) == 0) { bit0++; } else { bit1++; } } if(bit0 < bit1) { result |= 0<<(bitlen - i); } else { result |= 1<<(bitlen - i); start+=len/2; } } return result; } int main() { unsigned char a[] = {1,1,1,4,4,5,5,6,7,8,9,10,11,12,13,14,15}; printf("%d\n",getRepeat(a,17,4)); unsigned char b[] = {1,3,4,5,5,6,7,8,9,10,11,12,13,14,15}; printf("%d\n",getLost(b,15,4)); return 1; }
3、两个向量的转置算法,i,n的最大公约数怎么出现在程序中。
i,n的最大公约数其实就是从头开始进行a[i]=a[2i] a[2i]=a[3i]的次数
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <windows.h> void reverse1(char c[], int i, int n) { int p = 0; int count = 0; if(i > 0 && n>=i) { while(count!=n) { int t = c[p]; int q = p + i; while((q%n)!=p) { c[(q-i)%n] = c[q%n]; count++; q+=i; } c[(q-i)%n] = t; count++; p++; } } //p为i,n最大公约数,即从第一个数开始进行c[i]=c[2i] c[2i]=c[3i]循环的次数 printf("%d",p); } int main() { int i = 0; char c[] ={'a','b','c','d','e','f','g','h'}; DWORD start, stop; start = GetTickCount(); reverse1(c,3,8); stop = GetTickCount(); printf("time: %lld ms\n", stop - start); for(i = 0; i < 8;i++) { printf("%c",c[i]); } printf("%c",'\n'); return 1; }
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <windows.h> void reverse1(char c[], int i, int n) { int p = 0; int count = 0; if(i > 0 && n>=i) { while(count!=n) { int t = c[p]; int q = p + i; while((q%n)!=p) { c[(q-i)%n] = c[q%n]; count++; q+=i; } c[(q-i)%n] = t; count++; p++; } } //p为i,n最大公约数,即从第一个数开始进行c[i]=c[2i] c[2i]=c[3i]循环的次数 printf("%d",p); } void reverse2(char c[], int i, int j) { char p; while(i<j) { p = c[i]; c[i] = c[j]; c[j] = p; i++; j--; } } int main() { int i = 0; char c[] ={'a','b','c','d','e','f','g','h'}; DWORD start, stop; start = GetTickCount(); reverse1(c,3,8); stop = GetTickCount(); printf("time: %lld ms\n", stop - start); for(i = 0; i < 8;i++) { printf("%c",c[i]); } printf("%c",'\n'); char d[] ={'a','b','c','d','e','f','g','h'}; start = GetTickCount(); reverse2(d,0,2); reverse2(d,3,7); reverse2(d,0,7); stop = GetTickCount(); printf("time: %lld ms\n", stop - start); for(i = 0; i < 8;i++) { printf("%c",d[i]); } printf("%c",'\n'); return 1; }
5、将向量abc转为cba
我想到的是在两向量转置的基础上abc->bac->cba
网上百度的方法是对abc取ar br cr 再取(arbrcr)r r表示对向量的转置。
6、给定某一个名字的按钮编码,返回匹配集合
这个题目跟查找变位词差不多,给每个名字编码,将编码一样的放在一起,并顺序排列,查找的时候二分查找就可以了。
7、题意都理解得不是很来。。。。。。。
8、n个元素的实数集,确认是否有k个元素的子集可以让总和至多为t
将n个元素排序,计算头k个数和与尾k个数和,如果t介于二者之间就有。