1つの配列に2つのスタックを実装する方法は?


15

まず、これは宿題の問題ではないと言いたいです。私はアルゴリズムの紹介-優れたプログラマーになるための有名なCLRSテキストを読んでいます。私はこの本で与えられた問題と演習を自分で解決しようとしています。

私が解決しようとしているエクササイズ10.1-2をから第10章基本データ構造 CLRS第二版から。その状態は次のとおりです。

1つの配列A [1..n]に2つのスタックを実装する方法を説明します。両方のスタックの要素の合計数がnでない限り、どちらのスタックもオーバーフローしないようにします。PUSHおよびPOP操作はO(1)時間で実行する必要があります。

私がこれまでに考え出した解決策は次のとおりです。

配列A [1..n]がS1 [1..i]S2 [i..n]の 2つのスタックを実装するようにします。

PUSH-S1およびPUSH-S2操作、スタックが「満杯」である場合、その後に要素をプッシュスタート他のスタック(例えば、スタック場合S1は新しい要素を押し込むことしようとしているときに一杯になった後にその要素をプッシュスタックS2およびその逆)。

このアプローチの問題は、どの要素がどのスタックに属しているかを「記憶」する方法がないため、POP-S1またはPOP-S2を確実に使用できないことです。スタックの要素が(キー、値)のペアであり、キーがスタック番号である場合、要素をポップするには、最悪の場合、iまたは(ni)回-O(n )(ここで間違っている場合は、お気軽に修正してください)、これはO(1)ではありません。

私はかなり長い間質問に頭を打ち続けてきました。私は正しい軌道に乗っていますか?誰かがこの問題を解決するための私の可能なポインターを与えることができますか?

一般に、これらの問題についてどのように「考える」べきですか?または、本当に知的な人だけがこの種の問題を解決できますか?これらのような問題に取り組む/解決する(つまり、経験を積む)ことで、私はこれで良くなりますか?

悟りを待っています。


3
「これらのような問題に取り組む/解決する(つまり、経験を積む)ことで、これがうまくなるのでしょうか?」私の経験では、これは間違いなくそうです。他に何もなければ、問題について複数の方法で考え、それだけでより多くの洞察力を開発します。私が最近言われたように、良いアイデアを持つための最良の方法は、多くのアイデアを持つことです。
G.バッハ

回答:


7

Yuvalが言ったことに加えて、もう1つのヒントがあります。スタックを特定の方法で配列に配置しそれに応じて成長の方向を修正するのに役立ちます。彼らは同じ方向に成長する必要はありません。


5

ここではいくつかのヒントがあります:

  1. スタックの1つが「アップ」し、もう1つが「ダウン」するはずです。
  2. どの要素がどのスタックに属しているかを「記憶」する方法はありません。追加の変数を使用して、そのようなものを支援することができます。(これは、最初のヒントで提案されたソリューションでより意味があります。)

1

最初のスタックは1から始まりnに向かって成長し、2番目のスタックはnから始まり1に向かって成長します。2つのスタックポインターが隣接しているときに要素がプッシュされると、スタックオーバーフローが発生します。


1

この方法は、使用可能なスペースを効率的に利用します。arr []に使用可能なスペースがある場合、オーバーフローは発生しません。アイデアは、arr []の2つの極端なコーナーから2つのスタックを開始することです。stack1は左端の要素から始まり、stack1の最初の要素はインデックス0でプッシュされます。stack2は右端の角から始まり、stack2の最初の要素はインデックス(n-1)でプッシュされます。両方のスタックは反対方向に成長(または縮小)します。オーバーフローをチェックするには、両方のスタックの一番上の要素間のスペースをチェックするだけです。


-1

別の解決策を考えました。配列を半分に分割し(または配列の長さが奇数の場合はできるだけ近い)、最初の要素を最初のスタックに入れ、2番目の要素を2番目のスタックに入れます。ポップしながら、これらの手順をたどることができます。しかし、この方法で実装すると、スタックの原則に違反しますか?


コンピュータサイエンスへようこそ!残念ながら、提案は機能しません。長さの配列内N合計サイズがNを超えない限りオーバーフローしない2つのスタックを格納できるはずです(したがって、空のスタックと長さのスタックに対処できるはずです)N)。いずれかのスタックが超過すると、ソリューションがオーバーフローしますN/2
デビッドリチャービー

-2

いくつかのヒント

配列を作る

奇数のインデックスを持つ配列要素はstack1用です

偶数インデックスの配列要素はstack2用です

これで、両方のスタックを左から右の方向に成長させることができます

両方のスタックの最上位を維持する変数を保持するだけです。配列を検索する必要はありません。

また、stack2が空のときにstack1がいっぱいになると、いくつかの変数を維持することにより、stack2内の追加のstack1要素を追跡できます。


これは非常に複雑です。既存の答えはすでに問題を解決するためのはるかに簡単な方法を提供しています
デヴィッドリチャービー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.