Coursera 学习记录 :排队游戏(通过递归调用的括号匹配问题以及while循环的巧用)

版权声明:知识内容为原创思考,转载请注明:转自 https://blog.csdn.net/SmartLoveyu/article/details/83385940

描述

在幼儿园中,老师安排小朋友做一个排队的游戏。首先老师精心的把数目相同的小男孩和小女孩编排在一个队列中,每个小孩按其在队列中的位置发给一个编号(编 号从0开始)。然后老师告诉小朋友们,站在前边的小男孩可以和他后边相邻的小女孩手拉手离开队列,剩余的小朋友重新站拢,再按前后相邻的小男孩小女孩手拉 手离开队列游戏,如此往复。由于教师精心的安排,恰好可以保证每两个小朋友都能手拉手离开队列,并且最后离开的两个小朋友是编号最小的和最大的两个小朋 友。(注:只有小男孩在前,小女孩在后,且他们两之间没有其他的小朋友,他们才能手拉手离开队列)。
请根据老师的排队,按小女孩编号从小到大的顺序,给出 所有手拉手离开队列的小男孩和小女孩的编号对。

输入

用一个字符串代表小朋友队列。字符串中只会出现两个字符(样例输入里用的是 括号但实际数据则不一定),
分别代表小男孩和小女孩,首先出现的字符代表小男孩,另一个字符代表小女孩。小孩总数不超过100

输出

按小女孩编号顺序,顺序输出手拉手离开队列的小男孩和小女孩的编号对,每行一对编号,编号之间用一个空格分隔。

样例输入
((()(())())(()))
样例输出
2 3
5 6
4 7
8 9
1 10
12 13
11 14
0 15

最终思路:

最重要的两点:
1、函数返回值的作用一定要清楚,并且意识到这个返回值会在之后用到。
2、while的循环,只要满足条件就会继续进行。(这一点我最开始忽略了,走了很多弯路)

观察((()(())())(())),会发现:女孩子的出现决定是否会配对离开,所以就可以在出现男孩子的位置进行函数调用,如果一直是男孩子,就一直调用,直到女孩子的出现。
女孩子的出现会匹配走它前面的男生,所以直接输出就可以,然后返回值指向下一个,否则返回的还是男生那个位置。
然后就是while函数神奇作用了,如果是女生,就会往下进行,如果是男生就继续循环。
并且关键的,使用i和j两个来计数,就保证了i记录住了男生的位置,通过满足条件,不断地配对离开,直至调用全部结束。

//简单的说,就是只有两种符号的数组,然后进行符号的匹配
//输出的正好组成一对的标号
//使用递归调用来思考,并且同样使用getline来获得数据
#include<iostream>
using namespace std;

/*
char line[100];
int i = 0;
int j = 1;

int reline(int i, int j) {
	if (line[i] == line[j]) {
		i++;
		j++;
		reline(i, j);
	}
	if (line[i] != line[j] && line[j] != '\0') {
		cout << i << j << endl;
		i--;
		j++;
		reline(i, j);
		//这个方法进行到这,就发现问题了,无法实现自动的减去并且保持序号不变。
		//所以,考虑能否先将女孩子的编号全部找出,然后再匹配呢?
		//采用ij两个变量,仍然有问题
	}
}

int main() {
	cin.getline(line,100);
	//方法失败,重新思考
}
*/

//重新整理思路,第一个符号表示男孩,但是后面的情况不知道,而男孩女孩匹配成功的前提是,只要出现了一个女孩,就可以和前面的男孩匹配
//所以,可以一个个往后看,只要出现一次女孩就往前匹配走一个男孩
char line[100];
char boy;

// ((()(())())(()))
int reline(int i) {
	int j = i + 1;//1
	//需要有两个记录
	while (line[j] == boy) {
		j = reline(j);//2 6
	}
	if (line[j] != boy && line[j] != '\0') {
		cout << i << ' ' << j << endl;//3
		return j + 1;//4
	}
	else {
		return j;//5
	}
}

int main() {
	cin.getline(line, 100);
	boy = line[0];
	reline(0);

	return 0;

}

猜你喜欢

转载自blog.csdn.net/SmartLoveyu/article/details/83385940