C ++で負の数と正の数の両方を含む文字列の配列を並べ替える方法は?


8
String str[]={"-123","89","-10","456"};

str文字列の配列であり、各文字列は整数の形式であり、この配列に対してO(n log n)時間内にソートを実行する必要があります。

の文字列はstr、正と負の両方の整数を表すことができます。これらの文字列の最大長は1024文字です。

この問題の1つの解決策は、文字列を数値に変換し、これとは別に比較することです。この問題の他の解決策はありますか?


1024文字–つまり数字–には非常に大きな整数が必要になります...
アコンカグア

@RSahu私の間違い私は今質問を編集しました
Emp1 '23

@Aconcaguanはい、私はそのためにcppのブースト多精度ライブラリを使用しました
Emp1

文字列ベースの比較を行う回答のアイデアの別のバージョン:リストを負の部分と負でない部分に分割し、各カテゴリに2つの単純な比較関数を使用して部分をソートできます。
aschepler

回答:


13

別の解決策は、独自の比較関数を実装することです。

  • 両方の文字列の最初の文字を確認してください。一方が数字で始まり、もう一方がで始まる-場合、で始まる文字列- は小さい方の数字です。
  • 両方の文字列が数字で始まる場合は、文字列の長さを比較します。文字列が短いほど数値は小さくなります。両方の文字列が同じ長さの場合、標準の文字列比較を実行します。
  • 両方の文字列がで始まる場合-は、文字列の長さを比較してください。長い文字列は小さい数です。両方の文字列が同じ長さの場合は、標準の文字列比較を実行しますが、結果は否定します。

ただし、先行ゼロはないと想定する必要があります。文字列の長さを考慮する場合、これらは無視する必要があります。負のゼロ("-0")が存在する場合、通常のゼロの前に並べ替えられますが、それは私には問題ないようです...
アコンカグア

3
これは簡単に修正できます。インデックスfrom find_first_not_of("0")を使用してそれらをcompare()オーバーロードに渡し、比較の両側でpos / lenを要求します。
Tanveer Badar

@Aconcagua私は先行ゼロを考慮していなかったのは正しいです。その解決策を提供してくれた@ TanveerBadarに感謝します。負のゼロについては、正のゼロの前にそれらを並べ替えることも私には問題ないようです。
user3386109

12

これは、最小限の、潜在的に不十分な(先行ゼロ、空白などを処理しない)例です。

コメントはそれが何をしているのかを説明しています。:)

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

int main() {
  std::vector<std::string> strings = {
      "-1", "-1", "-20", "-4", "3", "0", "-0", "1", "20", "20", "44020",
  };

  // Assumes everything in "strings" has no whitespace in it.
  // Assumes everything in "strings" does not have leading zeroes.
  // Assumes everything in "strings" is an ascii representaion of an integer.
  // Assumes everything in "strings" is nonempty.
  std::sort(strings.begin(), strings.end(),
            [](const std::string &a, const std::string &b) {
              const bool a_is_negative = a[0] == '-';
              const bool b_is_negative = b[0] == '-';
              if (a_is_negative != b_is_negative) {
                // If they have different signs, then whichever is negative is
                // smaller.
                return a_is_negative;
              } else if (a.length() != b.length()) {
                // If they have the same sign, then whichever has more
                // characters is larger in magnitude. When the sign is negative,
                // the longer (more digits) number is "more negative". When
                // positive, the longer (more digits) number is "more positive".
                return (a.length() < b.length()) != a_is_negative;
              } else {
                // Otherwise a lexicographic comparison of "a" and "b" will
                // determine which string is larger in magnitude. Using the same
                // logic above, we account for the "negative vs. positive"
                // comparison.
                return (a < b) != a_is_negative;
              }
            });

  for (const auto &str : strings) {
    std::cout << str << " ";
  }
  std::cout << std::endl;
}

ああ、他の答えは私が私の応答で書いたのと同じ論理を概説しているようです。彼らは最初でしたが、私はこれを残しておきます。私はコードを使って私の反応を表現し、彼は言葉を使いました。:)
druckermanly

(末尾の)戻り値の型を提供する場合、boolへの明示的な変換は必要ありません。個人的にはもっと読みやすいと思います。の!=代わりにを使用^してブール値でも同じ結果を得ることができますが、結果はすでにブール値であり、再び明示的なキャストが廃止されます(さらに括弧も...)。
アコンカグア

1
くそー、あなたは私の(機会)答えを盗んだ:私のデモをコリルで。;-)
Scheff

素敵な@Aconcagua-クリーンなコードを書くことを考えるのではなく、怠惰で考えを書いていた。回答を実質的に変更しないため、私はあなたの提案を採用しました。
druckermanly

ラムダは問題ないかもしれませんが、ラムダは大きいので、代わりに専用の関数(less_as_number?)を使用するのが理にかなっていると思います。
Jarod42
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.