SOJ-1021-Couples算法配合数据结构的美

最喜欢写的还是算法

这次也是一篇算法的文字(不敢说文章,hihi)


!!!要注意!!!

我没打算把这篇文章写出一般的算法博文那种感觉,我这次要让那些就算很少接触代码的人都能理解数据结构和算法的美

(我知道排版很丑,略略略)


题目算法配合数据结构的美

在以前,一直听师兄师姐(90%师兄,至于为什么,自己想),还有很多老师都在说,“一些算法只有配合上一定的数据结构才能做到很好”(大概就这意思,我也记不清了,略略略~)

今天,做了这道题目之后,对于这句话有了一个很深的体会,特来分享给大家。

//Anyway,我们还是先看题目吧【不用担心自己看不懂下面的题目,只要是你能够看懂下面这段话是在说什么意思就好了,如果你看不太懂什么意思,我会在题目最下面解释的,所以,可以直接跳过题目】

1021. Couples

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

N couples are standing in a circle, numbered consecutively clockwise from 1 to 2N. Husband and wife do not always stand together. We remove the couples who stand together until the circle is empty or we can't remove a couple any more.

Can we remove all the couples out of the circle?

Input

There may be several test cases in the input file. In each case, the first line is an integer N(1 <= N <= 100000)----the number of couples. In the following N lines, each line contains two integers ---- the numbers of each couple.
N = 0 indicates the end of the input.

Output

Output "Yes" if we can remove all the couples out of the circle. Otherwise, output "No".

Sample Input

4
1 4
2 3
5 6
7 8

2
1 3
2 4

0

Sample Output

Yes
No

Problem Source

ZSUACM Team Member


上面这个就是SOJ上的原题了。

题目意思:

就是在说,一群夫妇(所以说人数一定是偶数),围成一个圈。然后规定了一种操作(骚操作):如果夫妇相邻,那么就把这对夫妇从这个圈里面拿出来(作为单身狗,我的理解是他们能有幸在这个圈中站在一起,引起了大家的羡慕,然后就把这对夫妇给踢出去

然后不断地进行这样的操作(假设是无限次),那么最终能不能把所有人都拿出去呢?

如果是,就输出“Yes”

否则就输出“No”

//=======================描述完成了===========如果还是没有看懂,我就.... emmmm=========//

输入的情况是:

先输入每次测试的夫妇对数 n (就是有多少对,不是log,emmm)

然后就输入在这个围起来的圈里面,这对夫妇的编号//连续n行


如果输入的n为0就跳出循环

否则就接着输入,输出

//描述了这个题目了,如果你有兴趣,可以去把这个题目再看一遍(锻炼英语阅读)


对于这个题目有很多种解法:我就打出了两种,还有我一好朋友遇到这个题目的时候,他遇到了TLE( Time Limit Exceeded)和WA(Wrong Answer)。Hahhhh,一个劲地黑好友,突然担心他以后跟我漂流瓶联系。


他采用的方式是:

运用数据结构:队列(也就是Queue),很少打代码的人就只需要明白,这是个放数据的方法,然后,先放到这个结构中的数据,要是要拿出来就会被先被拿出来,也就是“先入先出”。

思路是:

先将这些夫妇标记,然后第几个夫妇,就用 几来比较他们,比如,如果是第一对夫妇,就是设置为1,一开始输入数据的时候,我们是知道的这对夫妇的所在位置的,所以就用一个数组把这两个个位置标记为1,2,3,

如:

3

1 2 

3 4 

5 6 

那么,在这新的数组里面就是

A[0] = 0//任意数据,这个其实也是可以用到的,但是老师给的测试数据很大所以也就无所谓这一个位置了(不是比赛,对么?)

此后就是

1 1 2 2 3 3

如果是

4

1 3 

2 4

5 7 

8 6

A[0] = 0;//其他也是可以的

此后就是

1 2 1 2 3 4 3 4

//仔细体会一下。为什么要讲这个呢?因为,我也是用类似于这种的方式来进行标记的~

他采用的是队列Queue

那么他接下来,就是把这些点就全部都放到一个队列里面。(1次操作)

然后,开始进行循环

每次,第一个点跟它后面的那个点对应的数是否相等,我们之前不是说了么,这数组或者是后来得到的队列的内容是都在说这个人是属于第几对夫妇。如果是相等的,那么我们就知道这个是一对夫妇。

如果相等,就把他们拿走;如果不相等,就把前面那个点放到后面去(很符合这个操作的意思)


反反复复,你们可以试一下,在纸上算一下

如果这个数组是:

1 2 3 4 5 5 4 3 2 1 

的时候

要遍历的话,我估计了一下

对于一个长度为n的数组

你要做的事是,每一次循环走过 n - 1个点,每次都要看一次,结果一次看之后,就会少掉4个点,但是进行了n次操作

也就是 n + n - 4 + n - 4 - 4 + ... + 0

这是在完成的情况 那这个复杂度其实是 O(n^2)的

按照老师给的数据,这个是不能过的。这就是他为什么会超时。



我的策略是:

采用栈作为数据结构:做的事情是后入先出。即,后输入的数据就会被拿出来

策略描述:

对于每次放到栈中,都考虑下是否能被处理。

所以遍历完了所有点之后,就可以看出是否可以解决,就只需要走完一遍这些点就好了,那么也就是O(n)的复杂度,那么看到这,就可以知道了复杂度被下降了一个量级,甚至会更多,那么时间上就会更快了。


还是拿那个数据作为例子:

如果这个数组是:

1 2 3 4 5 5 4 3 2 1 

那么放到栈当中,一直到第5个时候都没有进行到删除的操作。

到第5个入栈以后,到了第六个和第五个是一样的,那么就会跟第五个构成配对,而在计算机的操作来看,就是不管第6个数据,直接把栈顶给去掉,然后跳掉,同理,当走完了,到终点的时候,我们只需要看一下在这栈中是不是空的,如果是空的,那么就输出“Yes”,否则就是“No”

然后时间的复杂度是O(n)

感受到了么?这就数据结构和算法的美,在某种结构,配合某种算法之后,这个时间和空间上的复杂长度都会不一样。


这就是我对于算法和数据结构的一个偶然的发现。希望能给大家提供到帮助


最后,附上我的代码:(如果还有人没看懂的话,可以在评论区留言,我看到就会回复)

#include <iostream>
#include <stack>
using namespace std;
int main(){
	int n;
	while (cin >> n && n){
		int tl,tr;
		int arr[200002];
		for (int i = 1; i <= n; ++i){
			cin >> tl >> tr;
			arr[tl] = tr;
			arr[tr] = tl;//储存关系 
		}
		stack<int> s;
		for (int i = 1; i <= 2*n; ++i){
			if (s.empty() || s.top() != arr[i]) {
				s.push(i); 
			} else {
				s.pop();
			}
		} 
		if (s.empty()){
			cout << "Yes"<<endl;
		} else {
			cout << "No"<<endl;
		} 
	}
} 





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值