挑战面试编程:单词翻转、高斯公式、魔方矩阵、黑白球、3n+1

      挑战面试编程:单词翻转、高斯公式、魔方矩阵、黑白球、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>


理解变量start 和end:


运行实例:

挑战面试编程:单词翻转、高斯公式、魔方矩阵、黑白球、3n+1_第1张图片


说它简易,是因为它还不能处理诸如:句子中有括号()、有引号“”、有分号:等等的类型,如果考率这么多情况,

代码的逻辑判断就会异常复杂,希望后续完善它。



题二:

         高斯在上小学时发明了等差数列求和公式: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>


运行:

挑战面试编程:单词翻转、高斯公式、魔方矩阵、黑白球、3n+1_第2张图片


这种代码只能算是解决了问题,但效率很低,有更好的解法吗?


题三:

打印魔方矩阵:如三阶的:

8 1 6

3 5 7

4 9 2

规律是:

  1. 将“1”放在第一行中间一列;
  2. 从“2”开始直到n×n为止各数依次按下列规则存放:每一个数存放的行比前一个数的行数减1,列数加1;
  3. 如果上一个数的行数为1,则下一个数的行数为 n(指最下一行); 
  4. 当一个数的列数为 n,下一个数的列数应为1,行数减1; 
  5. 如果按上面规则确定的位置已有数,或上一个数是第 1行第 n列时, 则把下一个数放在上一个数的下面。

看到了其他人的解法,不过觉得太罗嗦,我的代码:

<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.取出的球组合只有三种:

  • 双白
  • 双黑
  • 一白一黑
2.按放回效果看只有两种:
  • 双白、双黑:放回白球
  • 一白一黑:放回黑球
3.根据2,只有对于袋子而言只有两种效果:
  • 双白、一黑一白:袋中黑球不变,白球减一 (类一)
  • 双黑:袋中黑球减二,白球加一 (类二)
4.袋子里的球数是一个一个减少的(取两个,放回一个嘛),所以最后肯定可以只剩一个

我们可以看出:
无论是类一还是类二的操作:黑球数的奇偶性保持不变,白球数则奇偶轮替。
如是我们可以下结论,如果最开始黑球数是偶数个,那么最后黑球一定没有,那就是说最后的一个球是白球;如果黑球数是奇数个,则最后剩下的一定是黑球。
最后的结果取决于黑球数的奇偶性。若黑球有偶数个,则肯定剩白球;若是奇数个,则肯定剩黑球。

代码如下:
<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>



所有内容的目录

  • CCPP Blog 目录

你可能感兴趣的:(魔方矩阵,3n+1,高斯公式,黑白球,单词翻转)