问题:给你一个数组 array,以及一个特定值 sum,找出数组中所有和为sum 的两个数对。
/*Solution 1
1.建立一个hash table,把数组中的所有元素映射到hash table中,
2 遍历array中的每一个元素i,针对对每个元素i,首先删除hash table中的此元素i(避免冗余),
然后查找 sum-i 是否在hash table中,如果在则找到一对数,否则继续遍历。
空间复杂度O(n),时间复杂度O(n).
*/
/* Solution 2:
1. 排序数组 最好的时间复杂度O(nlogn)
2. 遍历数组,针对每个元素i,在i元素后面的数列中二分查找 sum-i ;最坏的时间复杂度为 O(nlogn)
总的时间复杂度:O(nlogn)
*/
/* Solutin 3:
1. 排序数组 最好的时间复杂度O(nlogn)
2. 前后遍历数组,过程见函数printPariSums(); O(n);
*/
void printPairSums(int *array,int len,int sum){
sort(array,array+len); // 升序排列
cout<<endl;
int first=0;
int last=len-1;
int temp_sum;
while(first<last){
temp_sum=array[first]+array[last];
if(temp_sum==sum){
cout<<array[first]<<"+"<<array[last]<<endl;
++first;
++last;
}
else if(temp_sum<sum)
++first;
else
--last;
}
}
void main(){
int array[10]={4,5,12,1,-1,-4,10,11,14,-2};
printPairSums(array,10,9);
}
问题2:随机数问题。给定rand5() (随机生成1-5),怎么构成一个Rand7(),随机生成的数在1-7之间。
/*
随机生成,在于每个数要等概率。
方法1. 多次rand(0,1) { 生成0或1 的函数 }, 组合法,如k=3次运行rand(0,1) ,可有000,001,010,011...111 把个数,
即有8个范围,区间为[0,2^k)每个数概率相等
方法2. 扩大区间映射
较为详细的讲解可见<http://www.cnblogs.com/dwdxdy/archive/2012/07/28/2613135.html>
这里给出一个实现
*/
int rand7(){
while(true){
int sum=5*(rand5()-1) //产生0,5,10,15,20
+(rand5()-1); //产生0,1,2,3,4, 两者相加使sum正好为0,1,2,...24,每个数的产生概率相等
if(sum<21) // 取前21个数(0,1,...20 )
return sum%7+1; // 模除+1,正好为1-7.
}
}
问题3:找出两个数中的最大数,不能用if-else 以及任何比较运算符
思考过程:if a>b. return a, else return b;
if a-b>0 return a,else return b;
if a-b>0 let k=0;else let k=1; return a-k(a-b);
let c=a-b; let k 为c的符号位,return a-k*c;
int getMax(int a,int b){
int c=a-b;
int k=(c>>(sizeof(int)-1))&0x1;
return a-k*c;
}
问题4:就地交换两个数,不用任何临时变量
void swap(int a,int b){
cout<<a<<endl;
cout<<b<<endl;
a=a^b;
b=a^b;
a=a^b;
cout<<a<<endl;
cout<<b<<endl;
}
问题5:统计n!中末尾0的个数。
/* 5*2=10,所以5会贡献一个0,5的倍数都会贡献一个0;25=5*5 会贡献2个0,同理125会贡献3个0...
所以要统计5的倍数的个数,25倍数的个数,125倍数的个数...
*/
int numbersOfZeros(int num){
int count=0;
int i=0;
if(num<0){
cout<<"no zero"<<endl;
return -1;
}
for(i=5;num/i>0;i*=5){
count+=num/i;
}
return count;
}
int main(){
int num=17;
int64_t sum=1;
int i=1;
for(i=1;i<=num;i++)
sum*=i;
cout<<"sum="<<sum<<endl;
cout<<"0 nums="<<numbersOfZeros(num)<<endl;
return 0;
}
问题6 统计数字x的二进制中1的个数有多少个
int main(){
int x;
cin>>x;
while(x){
// 统计x的二进制中1的个数有多少个?
int count=0;
cout<<"x 的16进制是:"<<hex<<x<<endl;
while(x){
count++;
x=x&(x-1);
}
cout<<"x 中1的个数为"<<count<<endl;
cin>>x;
}
return 0;
}
当然,也可以用移位法。
问题7: 计算两数之和,不用+ 及其他算数操作符。
// 思考:计算机加法是如何实现的?异或 表示的是什么?与 & 表示的又是什么?
int add_no_arithmetic(int a,int b){
if(b==0) return a;
int sum=a^b; //^ 计算两者之和,不考虑进位
int carry=(a & b)<<1; // & 计算出进位,左移一位
add_no_arithmetic(sum,carry);
}
问题8:从n个数中,随机选出m个数
// 需要注意的问题或者需要问清楚面试官:这m个数可以有相同的吗?实际上不应当相同,也就是我们要解决一个数可能被选择两次的问题
int* PickRandom(int array[],int n,int m){
int *mp=new int[m];
for(int i=0;i<m;i++){
int index=rand()%(n-i)+i;// 范围的控制,避免选择前面的"dead"元素
mp[i]=array[index];
array[index]=array[i]; //把已经选择的元素(称为"dead"元素)交换到数组的前面,array[i] 作为"dead" 元素,不会被搜寻
}
return mp;
}
int main(){
int a[10]={3,23,1,-56,8,23,45,233,0,1234};
int *p=PickRandom(a,10,5);
for(int i=0;i<5;i++)
cout<<p[i]<<" ";
cout<<endl;
}
问题9:在 0~n (包括n) 这些数字中有多少个2呢?
int count2(int n){
if(n==0) return 0;
int power=1;
while(power*10<n)
power*=10;
int first=n/power;
int remainder=n%power;
int nTwosFirst=0;
if(first>2)
nTwosFirst+=power;
else if(first==2)
nTwosFirst+=remainder+1;
int nTwosOther=first*count2(power-1)+count2(remainder);
return nTwosFirst+nTwosOther;
}
void main(){
int n;
cin>>n;
while(n){
cout<<"0-"<<n<<" 中2的个数是:"<<count2(n)<<endl;
cin>>n;
}
}
问题10,计算1-100的和,不可使用while,if else ,三目运算法 等语句 (类似的题有 输出1,2,3,。。。。100 序列)
2013-9-27 记:::
首先想到递归,其次用 && || 来结束递归操作
int sum (int n){
int sum=0;
int x=n && (sum=f(n-1));
return sum+n;
}
// 输出1到n, (假定 && 会返回1)
int f(int n){
cout<<( n && f(n-1) )*n+1<<endl;
return 1;
}
调用 f(n-1)