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

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

[[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バイアス

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

ブログ    
ブログ    
ブログ    
ブログ    
ブログ    

推薦する

...

顔認識は「ワーテルロー」に見舞われ、ビッグデータが将来の方向性を明らかに

顔認識技術の利用が増えるにつれ、さまざまなリスクが徐々に明らかになってきています。 CCTVの「3....

AI技術が世界の感染症対策に情報提供を支援

最近、SingularityNETのCEOであるベン・ゲルツェル博士は、COVID-19サミットを開...

目から鱗!ヘルスケアと自動車業界における AI の興味深い応用例 11 選

この記事は公開アカウント「Reading Core Technique」(ID: AI_Discov...

3つの勾配降下法アルゴリズム(BGD、SGD、MBGD)の違い

序文ネットワークをトレーニングするときに、batch_size を設定することがよくあります。この ...

2019年にロボット分野で注目すべき5つのトレンド

2019 年に注目すべき 5 つのロボット トレンドは次のとおりです。 [[259551]] 1. ...

...

新しいマルチモーダル大型モデルがリストを独占!画像とテキストの混合入力をサポートしているので、知識がわからなくても学習できます

マルチモーダル大型モデルファミリーに新しいメンバーが加わりました!複数の画像とテキストを組み合わせて...

...

将来、ロボットは手術を支援し、反復作業をより効率的に実行できるようになるかもしれない。

人々は人工知能の急速な発展と、さまざまな業界でのその応用事例を目撃してきました。ヘルスケアは、AI、...

MetaHuman の効果は素晴らしいです!しかし、メタバースだけを考えると、パターンは少し小さくなります。

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

...

清華大学唐傑チーム: NLP事前トレーニングモデルの歴史の簡単な紹介

[[422829]]この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI...

金融ロボットの解読:毒ではなくアシスタント

[[231414]]会計、税務、監査などの業務でロボットが人間に取って代わったらどうなるか想像してみ...

ChatGPTを開発に組み込む10の実証済みの方法

絶えず変化するテクノロジー環境において、ChatGPT とその AI チャットボットは先頭に立って、...