挑战面试编程:单词翻转、高斯公式、魔方矩阵、黑白球、3n+1
题一:
把一字符串如"I love you."变为"you. love I"。
分析:
这并不是一简单的字符串reverse的操作,在reverse的过程中要保持单词本身的字母顺序。这就要求我们找到单词中间的间隔,显然是空格,或者是标点。单词也并非只是字母,也有可能是数字。
于是我们总结:两个标点或空格之间的内容,我们把它当做一单词。细节还得看代码……
代码:
这是一段简易的代码:
<span style="font-size:18px;"> #include<iostream> using namespace std; char* reverseWords(const char *s,char *t) { assert(s&&t); int slen=strlen(s); int start,end,begin=0; //start指向一个单词的起始位置的前一个,end表示结束位置的后一位 start=end=slen-1; while(start>=0 && !(isalpha(s[start]))) //从右向左,找第一个字母出现的位置 start--; while(start>=0) { while(start>=0 && isalnum(s[start])) start--; //此时start的位置要么是空格,要么就是标点 memcpy(t+begin,s+start+1,end-start); //以下的调整需画图理解 begin+=end-start; end=start; start--; } *(t+begin)='\0'; return t; } int main() { char *s="I love you."; cout<<"原字符串"<<endl; cout<<s<<endl; //构建一新的字符串存储变换后的 char *t=new char[strlen(s)+1]; //多一个位置存放'\0' reverseWords(s,t); cout<<"翻转……"<<endl; cout<<t<<endl; delete []t; return 0; }</span></span>
运行实例:
说它简易,是因为它还不能处理诸如:句子中有括号()、有引号“”、有分号:等等的类型,如果考率这么多情况,
代码的逻辑判断就会异常复杂,希望后续完善它。
题二:
高斯在上小学时发明了等差数列求和公式:1+2+..+100=5050。现在问题在于给你一个正整数n,问你他可以表示为多少种连续正整数之和?(自身也算)。(取自csdn高校俱乐部线上编程挑战赛)
很简单直接给代码:
<span style="font-size:18px;"> #include<stdio.h> void print(int start,int end,int n) //负责打印 { for(int i=start; i<end; i++) printf("%d+",i); printf("%d=%d\n",end,n); } int main() { int n; printf("输入给定的正整数:"); scanf("%d",&n); while(n<=0) { printf("输入数据有问题!,请重新输入:"); scanf("%d",&n); } int count=1; //代表种类,至少自身可以,所以赋初值1 int start=1; int end=1; int sum=start; while(start<=n/2) { while(sum<n) { end++; sum+=end; if(sum==n) { count++; print(start,end,n); } if(sum>n) break; } start++; end=start; sum=start; } printf("%d=%d\n",n,n); printf("一共有%d种\n",count); return 0; }</span></span>
这种代码只能算是解决了问题,但效率很低,有更好的解法吗?
题三:
打印魔方矩阵:如三阶的:
8 1 6
3 5 7
4 9 2
规律是:
看到了其他人的解法,不过觉得太罗嗦,我的代码:
<span style="font-family:Courier New;"> <span style="font-size:18px;"> #include<iomanip> #include<iostream> using namespace std; int main() { int i,j; int n; cout<<"输入方阵阶数(奇数):"; cin>>n; while(n<=0||n%2==0) { cout<<"输入的阶数有问题!,请重新输入:"; cin>>n; } int **a=new int*[n]; for(i=0; i<n; i++) a[i]=new int[n]; for(i=0; i<n; i++) //初始化 for(j=0; j<n; j++) a[i][j]=0; int k=1; i=0; j=n/2; int a1,a2; a[i][j]=k++; while(k<n*n+1) { //记录旧值 a1=i; a2=j; //按规律二,变化新值 i=(i-1+n)%n; j=(j+1)%n; //对于规律五的判断 if(i==n-1 && j==0) { i=1; j=n-1; } //还是规律五的判断 if(a[i][j]) { i=a1+1; j=a2; } //经过以上的判断,确定赋值位置 a[i][j]=k++; } cout.setf(ios::left); for(i=0; i<n; i++) { for(j=0; j<n; j++) cout<<setw(4)<<a[i][j];; cout<<endl; } delete[]a; system("pause"); return 0; }</span> </span>
题四 黑白球
一个袋子里有两种颜色的球,黑色和白色,你每次从中取出两个球,如果是同色的,则在袋子里放一个白球,否则放回一个黑球。 最后袋子里剩下一个球,你能最后判断球的颜色么?(取自csdn高校俱乐部线上编程挑战赛)
分析:
题目其实不难,代码很简单,不过得分析清楚。我们得明白以下几点:
1.取出的球组合只有三种:
<span style="font-family:Courier New;"> <span style="font-size:18px;"> #include<iostream> using namespace std; int main() { int w, b; while (cin >> w >> b) { if (b % 2 == 0) cout << "WHITE" << endl; else cout << "BLACK" << endl; } return 0; }</span> </span>
题五 3n+1
对任何一个自然数n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把(3n+1)砍掉一半。这样一直反复砍下去,最后一定在某一步得到n=1。给定的任一不超过1000的正整数n,简单地数一下,需要多少步(砍几下)才能得到n=1?(取自csdn高校俱乐部线上编程挑战赛)
分析:
题目其实很简单,但很多人没看懂,我们得明白每一步操作后的新值作为n。可得代码:
<span style="font-family:Courier New;"> <span style="font-size:18px;"> #include<iostream> using namespace std; int fun(int n) { int count = 0; while (n != 1) { if (n % 2 == 0) n /= 2; else n = (3 * n + 1) / 2; count++; } return count; } int main() { int n; while (cin >> n) cout << fun(n) << endl; return 0; } </span></span>
所有内容的目录