题目: 输入两个整数序列。其中一个序列表示栈的push顺序,
判断另一个序列有没有可能是对应的pop顺序。
为了简单起见,我们假设push序列的任意两个整数都是不相等的。(这是原题目的限制,下面算法没有这个限制)
比如输入的push序列是1、2、3、4、5,那么4、5、3、2、1就有可能是一个pop系列。
因为可以有如下的push和pop序列:
push 1,push 2,push 3,push 4,pop,push 5,pop,pop,pop,pop,
这样得到的pop序列就是4、5、3、2、1。
但序列4、3、5、1、2就不可能是push序列1、2、3、4、5的pop序列。
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)就是所有可能的出栈数。
根据等价代码有:
非递归算法如下:
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操作却展示出了如此惊人的复杂性,
这也间接诠释了为什么栈,如此简单的数据结构在计算机科学中如此重要的地位!!!