微软面试100题-栈的push-pop序列问题

 题目: 输入两个整数序列。其中一个序列表示栈的push顺序,

 判断另一个序列有没有可能是对应的pop顺序。

 为了简单起见,我们假设push序列的任意两个整数都是不相等的。(这是原题目的限制,下面算法没有这个限制)

 比如输入的push序列是12345,那么45321就有可能是一个pop系列。

 因为可以有如下的pushpop序列:

 push 1push 2push 3push 4poppush 5poppoppoppop

 这样得到的pop序列就是45321

 但序列43512就不可能是push序列12345pop序列。

CSDN https://github.com/wangjufan/Algorithms/blob/master/Problems/Stack.h

BOOL isReasonablePopSequenceForPushSequence(NSArray * pushSequence,NSArray * popSequence){

    

    BOOL matched = YES;

    int indexPush = 0;

    

    NSUInteger size = [popSequence count];

    

    NSMutableArray * marks = [NSMutableArrayarrayWithCapacity:size];

    for (int i= 0; i<size; i++) {

        [marks insertObject:[NSNumbernumberWithBool:NO]atIndex:i];

    }

    

    for (int index =0; (index<size) && matched; index++) {

        NSUInteger popValue = [[popSequenceobjectAtIndex:index]integerValue];

        

        //move to previous unmarked position

        while (indexPush > 0) {

            if ([[marks objectAtIndex:indexPush]boolValue]) {

                indexPush–;

            }else{

                break;

            }

        }

        

        while (matched) {

            

            //move to the back unmarked position

            while ([[marks objectAtIndex:indexPush] boolValue]) {

                indexPush++;

                if (indexPush==size) {

                    matched = NO;

                    break;

                }

            }

            

            if (matched) {

                NSUInteger pushValue = [[pushSequenceobjectAtIndex:indexPush]integerValue];

                if (pushValue == popValue) {

                    [marks replaceObjectAtIndex:indexPushwithObject:[NSNumbernumberWithBool:YES]];

                    break;

                }else{

                    indexPush++;

                    if (indexPush ==size) {

                        matched = NO;

                        break;

                    }

                }

            }

            

        }

    }

    

    return matched;

}

 扩展1

 输入一个整数序列,表示一个栈的push顺序。求解一共有多少种出栈可能性。

unsigned long long allPossiblePopOrderNumber_Recursion_Obsolete3(unsigned int unpushed, unsigned int pushed)

{

    NSUInteger count = 0;

//    if (pushed == 0) {

//        if (unpushed>1) {

//            count += allPossiblePushPopNumber(unpushed-1, 1);

//        }else{

//            count += 1;

//        }

//    }else{

//        for (int i=0; i<= pushed ; i++) {

//            if (unpushed > 1) {

//                count += allPossiblePushPopNumber(unpushed-1, i+1);

//            }else{

//                count+=1;

//            }

//            

//        }

//    }

//    等价于

//    for (int i=0; i<= pushed ; i++) {

//        if (unpushed > 1) {

//            count += allPossiblePushPopNumber(unpushed-1, i+1);

//        }else{

//            count+=1;

//        }

//        

//    }

//    等价于

//    for (int i=0; i<= pushed ; i++) {

//        if (unpushed == 1) {

//            count+=1;

//        }

//    }

//    for (int i=0; i<= pushed ; i++) {

//        if (unpushed > 1) {

//            count += allPossiblePushPopNumber(unpushed-1, i+1);

//        }

//    }

//    等价于

//    if (unpushed == 1) {

//        for (int i=0; i<= pushed ; i++) {

//            count+=1;

//        }

//    }

//    if (unpushed > 1) {

//        for (int i=0; i<= pushed ; i++) {

//            count += allPossiblePushPopNumber(unpushed-1, i+1);

//        }

//    }

//    等价于

//    if (unpushed == 1) {

//        return pushed+1;

//    }

//    if (unpushed > 1) {

//        for (int i=0; i<= pushed ; i++) {

//            count += allPossiblePushPopNumber(unpushed-1, i+1);

//        }

//    }

//    等价于

    if (unpushed == 1) {

        count = pushed+1;

    }

    if (unpushed > 1) {

        for (int i=0; i<= pushed ; i++) {

            count += allPossiblePushPopNumber(unpushed-1, i+1);

        }

    }

    

    return count;

}

扩展问题1:

输入一个整数序列,表示一个栈的push顺序。求解一共有多少种出栈可能性。

下面做扩展问题的形式化表述:

设输入序列为n个整数,为1到n。

unpushed 表示没有入栈的元素个数,

pushed表示当前栈中元素个数,

poped表示出栈元素数目。poped + pushed + unpushed = n。

f(unpushed,pushed)表示当前情况下可能存在的出栈序列数目。有f(n,0)就是所有可能的出栈数。

根据等价代码有:

《微软面试100题-栈的push-pop序列问题》

《微软面试100题-栈的push-pop序列问题》

《微软面试100题-栈的push-pop序列问题》

《微软面试100题-栈的push-pop序列问题》

非递归算法如下:

unsigned long long allPossiblePopOrderNumber_NonRecursion_Obsolete1(unsigned int elementNum){

    

    NSMutableDictionary * currentCeos = [NSMutableDictionary dictionaryWithCapacity:0];

    NSMutableArray * currentKeys = [NSMutableArray arrayWithCapacity:0];

    

    NSMutableDictionary * nextCeos = [NSMutableDictionary dictionaryWithCapacity:0];

    NSMutableArray * nextKeys = [NSMutableArray arrayWithCapacity:0];

    

    unsigned int unpushed = elementNum;

    unsigned int pushed = 0; //key

    [nextKeys addObject:keyFor(pushed)];

    [nextCeos setObject:[NSNumber numberWithUnsignedLongLong:1] forKey:keyFor(pushed)];

    

    

    while (unpushed > 1 || [currentKeys count] > 0) {

        if ([currentKeys count] == 0) {

            currentKeys = nextKeys;

            nextKeys = [NSMutableArray arrayWithCapacity:elementNum];

            currentCeos = nextCeos;

            nextCeos = [NSMutableDictionary dictionaryWithCapacity:elementNum];

            unpushed -= 1;

        }

        

        pushed = [[currentKeys objectAtIndex:0] intValue];

        [currentKeys removeObjectAtIndex:0];

        NSUInteger ceo = [[currentCeos objectForKey:keyFor(pushed)] unsignedLongLongValue];

        [currentCeos removeObjectForKey:keyFor(pushed)];

        

        

        for (int i = 1; i<= pushed+1; i++) {

            

            NSString * key = keyFor(i);

            if ([nextKeys count] < i) {

                [nextKeys insertObject:key atIndex:i-1];

            }

            

            NSUInteger nextCeo = 0;

            if ([nextCeos objectForKey:key]) {

                nextCeo += [[nextCeos objectForKey:key] unsignedLongLongValue];

            }

            nextCeo += ceo;

            [nextCeos setObject:[NSNumber numberWithUnsignedLongLong:nextCeo] forKey:key];

        }

    }

    

    unsigned long long count = 0//sum of (key+1)* coe

    unsigned long long pre = 0;

    NSLog(@”%@”, nextCeos);

    for (NSString * key in nextKeys) {

        unsigned long long value = [[nextCeos objectForKey:key] unsignedLongLongValue];

        NSUInteger keyValue = [key longLongValue] + 1;

        count += keyValue * value;

        if (pre > count) {

            NSLog(@”-overflow–pre : %lld”, pre);

            NSLog(@”–overflow-count: %lld”, count);

        }

        pre = count;

    }

    return count;

}

element num = 1, possible = 1

element num = 2, possible = 2

element num = 8, possible = 1430

element num = 9, possible = 4862

element num = 10, possible = 16796

element num = 20, possible = 6564120420

element num = 30, possible = 3814986502092304

element num = 36, possible = 11959798385860453492


10个元素一个特定的入栈序列,其出栈就有16796种可能性。

20个元素就有惊人的6564120420可能性。

展示了一个特定的普通入栈序列,出栈时元素顺序所能表现出惊人的复杂性!!!
简单的数据结构特定的push顺序,与其对应的pop操作却展示出了如此惊人的复杂性,
这也间接诠释了为什么栈,如此简单的数据结构在计算机科学中如此重要的地位!!!

点赞