两端入栈

一:问题描述

Description: Much to Mr. Book’s amazement, his entire algorithm class has completed the homework that he assigned only the day before. The students have dumped their homework, one page per student, unceremoniously in a pile on his desk.
There are N students in the class, and each of them have a unique integer student ID from 1 to N. Mr. Book wants the homework to be sorted by student ID with the page from student #1 at the top,all the way down to the page to student #N at the bottom. Mr. Book is a lazy fellow. He doesn’t want to put much effort into sorting the pile himself.
To sort the homework, Mr. Book comes up with an idea which could be described as follows:Every time he moves a page, he’ll only move it from the original pile to his finished stack, which initially starts empty. Furthermore, he’ll only move the top or bottom page of the remaining pile, and he’ll only place it on the top or bottom of his destination stack. Is it possible for Mr. Book to sort the homework with such a method?

Input: Input begins with a line which contains an integer T , i.e. the number of test cases. For each case, there are two lines. The first contains the integer N , i.e. the number of students. The second contains a permutation of the integers from 1 to N . These are the students’ IDs in the order their homework appears in the pile, from bottom to top.

Output: For the i-th case, print a line containing “Case #i: ” followed by “yes” if Mr. Book can sort the homework by student ID, or “no” if he can’t.

Sample Input:
5
4
1 2 3 4
4
1 3 2 4
9
2 4 3 1 5 9 6 7 8
6
4 3 2 1 6 5
5
3 4 5 1 2

Sample Output:
Case #1: yes
Case #2: no
Case #3: no
Case #4: yes
Case #5: yes

二:题意解析

其实就是一个首尾进出栈的问题。对于一个序列,如 3 4 5 1 2.每次从首 或者 尾拿出一个元素,插入栈,看其是否可以 在允许 栈顶和栈底插入的情况下,形成 1 2 3 4 5的序列,可以输出yes,否则输出no.
那么 栈结构可以是这样的,3 -> 3 4-> 3 4 5->2 3 4 5->1 2 3 4 5,yes
再如序列:1 3 2 4. 如果入栈 1,然而后面只能入栈 3或者4,就不能连续。如果入栈 4,然而后面只能入栈1或者2.不能连续。故输出no.

三:思路

我们可以考虑2种情况
A:第一个入栈元素为序列左边
B:第一个入栈元素为序列右边
对于A,我们接下来 入栈剩余序列的左边或者右边,必须保证 入栈元素 和 栈顶或者栈底 的元素连续,如果不连续,则 A情况失败,如果 序列全部入栈,那么最小值为1,最大值为序列元素个数。
对于B,我们是同样的分析。

四:C代码

/*
1.运行环境:windows 7 + 32位系统 + vs2013
2.无差错控制,无安全检查,无特殊处理。
3.带刺的银杏 2015.05.18 于 苏州 (中雨)
*/
#include<stdio.h>

int flag_left = 0;  // 成功则修改为1

int judge_left(int a[],int len,int min,int max,int low,int high)  //a为序列,len是序列长度,min,max为当前栈中元素 最小值和最大值,low,high为待入栈的序列 的首尾指针。
{
    if(min == 1 && max == len)    //成功
    {
        flag_left = 1 ; 
        return 1;
        }
    if ( a[low] == min-1 )       //相当于入栈序列的左边
        return judge_left(a,len,a[low],max,low+1,high);
    else if(a[low] == max + 1 )
        return judge_left(a,len,min,a[low],low+1,high);
    else if(a[high] == min - 1)  //相当于入栈序列的右边
        return judge_left(a,len,a[high],max,low,high-1);
    else if (a[high] == max + 1)
        return judge_left(a,len,min,a[high],low,high-1);    
    else    
        return -1;               //两边都不能保证连续,故此次入栈失败,即 退出
} 

int main()
{
    int num,i,len,result1=0,result2=0,cases=0;
    int a[100];

    scanf("%d",&num);     //测试案例的个数
    while(cases++ < num)  //接受每个案例的输入
    {
        flag_left = -1;
        result1 = 0;      //记录A情况的结果
        result2 = 0;      //记录B情况的结果
        scanf("%d",&len);        
        for(i=0;i<len;i++)
            scanf("%d",&a[i]);
        judge_left(a,len,a[0],a[0],1,len-1);
        result1 = flag_left;
        flag_left = 0;
        judge_left(a,len,a[len-1],a[len-1],1,len-1);
        result2 = flag_left;
        printf("Case #%d:%s\n",cases,(result1 ==1 || result2 == 1)?"yes":"no"); 
    }   
}

五:小结

递归真是一种好办法,代码量如此少。同时,判断结束的条件 if(min == 1 && max == len) 也是蛮有意思的。值得一试。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值