データ構造とアルゴリズムの比較 バックスペースを含む文字列!

データ構造とアルゴリズムの比較 バックスペースを含む文字列!

[[441739]]

バックスペースで文字列を比較する

LeetCode の問題へのリンク: https://leetcode-cn.com/problems/backspace-string-compare

2 つの文字列 S と T がそれぞれ空のテキスト エディターに入力された場合、2 つの文字列が等しいかどうかを判定し、結果を返します。 # はバックスペース文字を表します。

注意: 空のテキストにバックスペース文字を入力すると、テキストは空のままになります。

例1:

  • 入力: S = "ab#c"、T = "ad#c"
  • 出力: true
  • 説明: S と T は両方とも「ac」になります。

例2:

  • 入力: S = "ab##", T = "c#d#"
  • 出力: true
  • 説明: S と T は両方とも "" になります。

例3:

  • 入力: S = "a##c"、T = "#a#c"
  • 出力: true
  • 説明: S と T は両方とも「c」になります。

例4:

  • 入力: S = "a#c"、T = "b"
  • 出力: false
  • 説明: S は「c」になりますが、T は「b」のままです。

アイデア

この記事では、空間計算量を伴うスタック シミュレーション方式と空間計算量を伴うダブル ポインター方式について説明します。

通常の方法(スタックの考え方を使用)

この問題では、明らかにスタックを使用する必要があります。この種のマッチング (消去) 問題も、スタックが得意とする分野です。私と一緒に学習する学生は、スタックとキューにおけるマッチング問題がスタックの強みであることを理解する必要があります。同様のことを行うためにスタックを使用することについては、すでに一度触れました。

したがって、この問題では、スタックの考え方を実際に使用できますが、最後に比較するときにスタック内の要素も比較する必要があるため、スタックを使用する必要はありません。これは少し面倒です。

ここでは、文字列をそのままスタックとして使用し、最後に追加とポップを行い、文字列には対応するインターフェースがあります。最後に比較するときは、2 つの文字列を比較するだけで済み、スタック内の要素を比較するよりも便利です。

コードは次のとおりです。

  1. クラスソリューション{
  2. 公共
  3. bool backspaceCompare(文字列S、文字列T) {
  4. string s; // スタックとして使用
  5. string t; ​​// スタックとして使用
  6. ( int i = 0; i < S.size ( ); i++) {
  7. S[i] != '#'の場合、 s += S[i];
  8. それ以外の場合 (!s.empty()) {
  9. s.pop_back();
  10.  
  11. }
  12. ( int i = 0; i < T.size ( ) ); i++) {
  13. T[i] != '#'の場合、t += T[i];
  14. それ以外の場合は (!t.empty()) {
  15. t.pop_back();
  16. }
  17. }
  18. (s == t)の場合、戻り値  true ; // 2つの文字列が等しいかどうかを直接比較する方が、スタックを使用するよりもはるかに便利です
  19. 戻る 間違い;
  20. }
  21. };

時間計算量: nはSの長さ、mはTの長さであり、時間計算量とも言える。

空間計算量: もちろん、上記のコードでは、処理 S と処理 T の繰り返しロジックがあることがわかります。この共通ロジックを抽出して、コードを次のように簡略化できます。

  1. クラスソリューション{
  2. プライベート:
  3. 文字列 getString(const string& S) {
  4. 文字列 s;
  5. ( int i = 0; i < S.size ( ); i++) {
  6. S[i] != '#'の場合、 s += S[i];
  7. それ以外の場合 (!s.empty()) {
  8. s.pop_back();
  9. }
  10. }
  11. sを返します
  12. }
  13. 公共
  14. bool backspaceCompare(文字列S、文字列T) {
  15. getString(S) == getString(T)を返します
  16. }
  17. };

パフォーマンスは依然として次のとおりです。

  • 時間の計算量:
  • 空間の複雑さ:

最適化方法(後ろから前へのダブルポインタ)

もちろん、この問題を解決するために使用する空間計算量もあります。

同時に、S と T を後ろから前へトラバースし (i は最初は S の末尾にあり、j は最初は T の末尾にあります)、# の数を記録し、消去操作をシミュレートし、# が使い果たされた場合は、S[i] と S[j] の比較を開始します。

アニメーションは次のとおりです。

S[i]とS[j]が同じでない場合は、falseが返されます。一方のポインタ(iまたはj)が最初に文字列の先頭に到達した場合も、falseが返されます。

コードは次のとおりです。

  1. クラスソリューション{
  2. 公共
  3. bool backspaceCompare(文字列S、文字列T) {
  4. int sSkipNum = 0; // Sの数を記録する
  5. int tSkipNum = 0; // Tの数を記録する
  6. int i = S.size ( ) - 1;
  7. int j = T.size ( ) - 1;
  8. 一方(1){
  9. while (i >= 0) { // 後ろから前へ、S# を削除します
  10. S[i] == '#'の場合、 sSkipNum++;
  11. それ以外{
  12. sSkipNum > 0 の場合、 sSkipNum --;  
  13. そうでなければ中断します。
  14. }
  15. 私 - ;  
  16. }
  17. while (j >= 0) { // 後ろから前に向かってTを削除します #
  18. T[j] == '#'の場合、tSkipNum++;
  19. それ以外{
  20. tSkipNum > 0 の場合、tSkipNum --;  
  21. そうでなければ中断します。
  22. }
  23. j --;  
  24. }
  25. // 後半の半分# は削除され、S[i] != T[j] と比較されます
  26. if (i < 0 || j < 0) break; // S または T がトラバーサルの終了に到達しました
  27. (S[i] != T[j]) の場合、戻り値 間違い;
  28. 私は--;j--;  
  29. }
  30. // SとTが同時に走査されることを示します
  31. (i == -1 && j == -1)の場合、戻り値 真実;
  32. 戻る 間違い;
  33. }
  34. };
  • 時間の計算量:
  • 空間の複雑さ:

その他の言語

ジャワ:

  1. // 通常のメソッド(スタックの考え方を使用)
  2. クラスソリューション{
  3. パブリックブールバックスペース比較(文字列s、文字列t) {
  4. StringBuilder ssb = new StringBuilder(); // スタックをシミュレートする
  5. StringBuilder tsb = new StringBuilder(); // スタックをシミュレートする
  6. // 2つの文字列を別々に処理する
  7. ( char c : s.toCharArray())の場合{
  8. (c != '#' )の場合{
  9. ssb.append(c); // スタッキングをシミュレートする
  10. } else if (ssb.length() > 0){ // スタックをポップするにはスタックが空でない必要がある
  11. ssb.deleteCharAt(ssb.length() - 1); // スタックのポップをシミュレートする
  12. }
  13. }
  14. ( char c : t.toCharArray())の場合{
  15. (c != '#' )の場合{
  16. tsb.append(c); // スタッキングをシミュレートする
  17. } else if (tsb.length() > 0){ // スタックをポップするにはスタックが空でない必要がある
  18. tsb.deleteCharAt(tsb.length() - 1); // スタックのポップをシミュレートする
  19. }
  20. }
  21. ssb.toString().equals(tsb.toString());を返します
  22. }
  23. }

パイソン

  1. クラスソリューション:
  2.  
  3. get_string(self, s: str) を定義します。
  4. bz = []
  5. i が範囲(len(s))内にある場合:
  6. c = s[i]
  7. c != '#'の場合:
  8. bz.append(c) # スタッキングをシミュレートする
  9. elif len(bz) > 0: # スタックをポップするにはスタックが空でない必要があります
  10. bz.pop() # スタックのポップをシミュレートする
  11. str(bz)を返す
  12.  
  13. def backspaceCompare(self, s: str, t: str) -> bool:
  14. self.get_string(s) == self.get_string(t)を返します
  15. 合格

行く

  1. getString関数(文字列)文字列{
  2. bz := []ルーン{}
  3. _の場合、c := 範囲 s {
  4. c != '#'の場合{
  5. bz = append(bz, c); // スタッキングをシミュレートする
  6. } else if len(bz) > 0 { // スタックをポップするにはスタックが空でない必要がある
  7. bz = bz[:len(bz)-1] // スタックポップをシミュレートする
  8. }
  9. }
  10. 文字列を返す(bz)
  11. }
  12.  
  13. func backspaceCompare(s 文字列, t 文字列) bool {
  14. getString(s) == getString(t)を返します
  15. }

JavaScript

  1. //デュアルスタック
  2.  
  3. var backspaceCompare =関数(s, t) {
  4.  
  5. const arrS = [], arrT = []; // スタックとして使用される配列
  6.  
  7. (let charの場合 ){
  8.  
  9. char === '#' ? arrS.pop() : arrS.push( char );
  10.  
  11. }
  12.  
  13. (let charの場合  t ){の
  14.  
  15. char === '#' ? arrT.pop() : arrT.push( char );
  16.  
  17. }
  18.  
  19. return arrS.join ( '' ) === arrT.join ( ' ' ) ; // 2つの文字列が等しいかどうかを比較する
  20.  
  21. };
  22.  
  23. //デュアルスタックの簡素化
  24.  
  25. var backspaceCompare =関数(s, t) {
  26.  
  27. 定数getString = s => {
  28.  
  29. arrS = [] とします。
  30.  
  31. (let charの場合 ){
  32.  
  33. char === '#' ? arrS.pop() : arrS.push( char );
  34.  
  35. }
  36.  
  37. arrS.join ( '' )を返します
  38.  
  39. }
  40.  
  41. getString(s) === getString(t) を返します
  42.  
  43. };
  44.  
  45. //ダブルポインタ
  46.  
  47. var backspaceCompare =関数(s, t) {
  48.  
  49. let sSkipNum = 0; // sの数を記録する
  50.  
  51. let tSkipNum = 0; // tの数を記録する
  52.  
  53. i = s.length - 1、j = t.length - 1とします。
  54.  
  55. while( true ) {
  56.  
  57. while(i >= 0){ // 後ろから前へ、s# を削除します
  58.  
  59. s[i] === '#'の場合、 sSkipNum++;
  60.  
  61. それ以外{
  62.  
  63. sSkipNum > 0 の場合、 sSkipNum --;  
  64.  
  65. そうでなければ中断します。
  66.  
  67. }
  68.  
  69. 私 - ;  
  70.  
  71. }
  72.  
  73. while (j >= 0) { // 後ろから前へ、t# を削除します。
  74.  
  75. t[j] === '#'の場合、tSkipNum++;
  76.  
  77. それ以外{
  78.  
  79. tSkipNum > 0 の場合、tSkipNum --;  
  80.  
  81. そうでなければ中断します。
  82.  
  83. }
  84.  
  85. j --;  
  86.  
  87. }
  88.  
  89. // 後半の半分# は削除され、s[i] != t[j] と比較されます
  90.  
  91. if (i < 0 || j < 0) break; // s または t が走査の終わりに到達しました
  92.  
  93. s[i] !== t[j] の場合、戻り値 間違い;
  94.  
  95. 私は--;j--;  
  96.  
  97. }
  98.  
  99. // s と t が同時に走査されることを示します
  100.  
  101. (i == -1 && j == -1)の場合、戻り値 真実;
  102.  
  103. 戻る 間違い;
  104.  
  105. };

<<:  知っておくべき6つのAIバイアス

>>:  クリスマスのギフトボックスにロボット犬を見つけますか?ボストン・ダイナミクスがイースターエッグをリリースしたが、ギフトボックスが逃げてしまった

ブログ    
ブログ    

推薦する

人工知能、機械学習、ディープラーニング

1. 人工知能と機械学習記事を始める前に、下の図 1.1 に示すように、人工知能、機械学習、ディープ...

エッジインテリジェンス: リアルタイムのデータ処理とインテリジェントな意思決定を実現する新世代のテクノロジー

ラボガイドエッジインテリジェンスは、人工知能 (AI) とエッジコンピューティングを組み合わせた新し...

漫画解釈: よく使われる機械学習アルゴリズムのトップ 10 を簡単に理解する

この記事を通じて、ML でよく使用されるアルゴリズムについて常識的に理解することができます。コードや...

考えてみると恐ろしいですね!人工知能は、成功率70%で人間の行動を操作することを学習したと疑われている。

人工知能に関しては、多くの人が懸念を表明しています。例えば、人類開発の最前線にいるホーキング博士とマ...

システム統合における10の将来のトレンド

システム統合は、ソフトウェア システム、情報システム、エンタープライズ システム、モノのインターネッ...

...

十分なデータを使用してモデルをトレーニングしたかどうかをどのように確認しますか?

[51CTO.com クイック翻訳]ディープニューラルネットワーク (DNN) には大量のトレーニ...

8x7B オープンソース MoE が Llama 2 に勝ち、GPT-4 に迫る!欧州版OpenAIがAI界に衝撃を与え、22人の企業が半年で20億ドルの評価額を獲得

オープンソースの奇跡が再び起こりました。Mistral AI が初のオープンソース MoE 大規模モ...

劉厳紅が7日間で1000万人のフォロワーを獲得した背後で、スマートフィットネス業界が静かに台頭している

ジェイ・チョウの『本草綱目』のメロディーにのせて、劉恒紅の健康指導が再び始まった。 7日間でフォロワ...

脳コンピューター知能はますます熱を帯びており、AIは将来重要な役割を果たす可能性がある

アメリカのSF大作では、脳の記憶を読んだり、脳を通じて他人をコントロールしたりすることがよく行われて...

...

時系列予測におけるディープラーニングの概要と今後の方向性の分析

2023年は大きな言語モデルと着実な普及の年です。時系列の分野ではそれほど大きな成果は得られていませ...

2020年中国インテリジェントIoT(AIoT)白書

インテリジェントなモノのインターネット(AIoT)は、2018年に登場した概念です。さまざまな情報セ...

RWKV の紹介: リニア トランスフォーマーの台頭と代替案の検討

RWKV ポッドキャストからの私の考えの一部を要約すると次のようになります: https://www...