データ構造とアルゴリズム: 単調に増加する数値

データ構造とアルゴリズム: 単調に増加する数値

[[439817]]

単調に増加する数字

LeetCode の問題へのリンク: https://leetcode-cn.com/problems/monotone-increasing-digits

負でない整数 N が与えられた場合、N 以下の最大の整数を見つけます。この整数は、各桁の数字が単調に増加するという事実を満たす必要があります。

(すべての隣接する数字 x と y が x <= y を満たす場合にのみ、整数は単調に増加すると言います。)

例1:

  • 入力: N = 10
  • 出力: 9

例2:

  • 入力: N = 1234
  • 出力: 1234

例3:

  • 入力: N = 332
  • 出力: 299

注: N は [0, 10^9] の範囲の整数です。

力ずくの解決法

質問は非常に単純なので、最初に思いつくのは力ずくの解決法です。私が代わりにやってみますが、結果は当然タイムアウトです!

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

  1. クラスソリューション{
  2. プライベート:
  3. ブールチェック番号( int数値){
  4. 整数 最大= 10;
  5. while (数値) {
  6. int t = 数値 % 10;
  7. 最大値>=t)の場合、最大値=t;
  8. それ以外 戻る 間違い;
  9. 数値 = 数値 / 10;
  10. }
  11. 戻る 真実;
  12. }
  13. 公共
  14. int monotoneIncreasingDigits( int N) {
  15. ( int i = N; i > 0; i --)の場合{  
  16. checkNum(i) の場合、 iを返します
  17. }
  18. 0を返します
  19. }
  20. };
  • 時間計算量: O(n * m) mはnの長さ
  • 空間計算量: O(1)

貪欲アルゴリズム

この問題では、N 以下の最大の単調増加する整数が求められるため、2 桁の数字を例に挙げます。

たとえば、98 の場合です。strNum[i - 1] > strNum[i] (非単調増加) になると、まず strNum[i - 1] -- にして、次に strNum[i] を 9 にして、整数が 89 になるようにします。これは、98 未満の最大の単調増加整数です。

この点をしっかり考えれば、この問題は簡単に解決できるでしょう。

局所最適: strNum[i - 1] > strNum[i] の場合、strNum[i - 1] -- とし、strNum[i] を 9 に設定します。これにより、これらの 2 つの数字が最大の単調増加する整数になることが保証されます。

グローバル最適値: N 以下の単調に増加する最大の整数を取得します。

ただし、局所最適値から大域最適値を導き出すには、トラバース順序とマークの開始点(一律 9 に変更)など、他の条件も必要です。

前から後ろへ移動しますか、それとも後ろから前へ移動しますか?

前から後ろへトラバースする場合、strNum[i - 1] > strNum[i] であれば、strNum[i - 1] を 1 減らします。ただし、このとき strNum[i - 1] を 1 減らすと、strNum[i - 2] より小さくなる可能性があります。

少し抽象的ですが、例えば332という数字を前から後ろへたどっていくと329になります。このとき、2は最初の数字の3より小さいので、実際の結果は299になるはずです。

したがって、前から後ろへトラバースすると、すでにトラバースされた結果が変わります。

次に、後ろから前へ走査することで、最後の比較の結果を再利用できます。332の値は後ろから前へ変化します: 332 -> 329 -> 299

トラバーサル順序が決定された後、局所最適解から大域最適解を推測できます。反例が見つからない場合は、貪欲法を試してください。

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

  1. クラスソリューション{
  2. 公共
  3. int monotoneIncreasingDigits( int N) {
  4. 文字列 strNum = to_string(N);
  5. // フラグは割り当て9の開始位置を示すために使用されます
  6. //フラグに値が割り当てられていない場合に2 番目のforループが実行されないようにするには、このデフォルト値を設定します。
  7. intフラグ = strNum.size ( );
  8. ( int i = strNum.size () - 1; i > 0; i -- ) {  
  9. strNum[i - 1] > strNum[i] の場合 {
  10. フラグ = i;
  11. strNum[i - 1] --;  
  12. }
  13. }
  14. ( int i = flag; i < strNum.size ( ) ); i++) {
  15. strNum[i] = '9' ;
  16. }
  17. stoi(strNum)を返します
  18. }
  19. };
  • 時間計算量: O(n) nは数の長さ
  • 空間計算量: O(n) は文字列を必要とするため、文字列に変換する方が便利である

要約する

この問題では、98 などの 1 つの例についてのみ明確に考える必要があります。strNum[i - 1] > strNum[i] (非単調増加) になると、まず strNum[i - 1] を 1 減らし、strNum[i] に 9 を割り当てて、整数が 89 になるようにします。対応する貪欲な解決策を自然に考えることができます。

貪欲さについて考えるときは、トラバースの順序も考慮する必要があります。後ろから前へトラバースすることによってのみ、最後の比較の結果を再利用できます。

最終的なコードを実装するときには、値 9 の割り当てを開始する場所をマークするためのフラグを使用するなどのいくつかのテクニックも必要です。

その他の言語

ジャワ:

  1. バージョン 1
  2. クラスソリューション{
  3. 公共  int monotoneIncreasingDigits( int N) {
  4. String[] 文字列 = (N + "" ).split( "" );
  5. int開始 = 文字列.長さ;
  6. ( int i = strings.length - 1; i > 0; i --) {  
  7. 整数.parseInt(文字列[i]) <整数.parseInt(文字列[i - 1]) の場合
  8. 文字列[i - 1] = ( Integer .parseInt(文字列[i - 1]) - 1) + "" ;
  9. 開始 = i;
  10. }
  11. }
  12. ( int i = start; i < strings.length; i++) {
  13. 文字列[i] = "9" ;
  14. }
  15. 戻る 整数.parseInt(String . join ( "" , strings));
  16. }
  17. }

Java バージョン 1 では、String 配列が作成され、Integer.parseInt メソッドが複数回使用されるため、時間とスペースの使用量が膨大になり、12 ミリ秒かかります。次のバージョンでは、char 配列をその場で変更するため、1 ミリ秒かかります。

  1. バージョン2
  2. クラスソリューション{
  3. 公共  int monotoneIncreasingDigits( int n) {
  4. (n==0)の場合は0を返します
  5. char [] chars = Integer .toString(n).toCharArray();
  6. int start = Integer .MAX_VALUE; //startの初期値は最大値に設定されます。これは、数値自体が単調増加しているときに、どの桁も9に変更する必要がない状況を防ぐためです。
  7. ( int i=chars.length-1;i>0;i --) {  
  8. (文字[i]<文字[i-1])の場合{
  9. 文字[i-1] --;  
  10. 開始=i;
  11. }
  12. }
  13. StringBuilder res=新しいStringBuilder();
  14. ( int i=0;i<chars.length;i++) {
  15. if (chars[i]== '0' &&i==0) continue ;//09のような状況を防ぐ
  16. (i>=開始)の場合{
  17. res.append( '9' );
  18. }そうでない場合はres.append(chars[i]);
  19. }
  20. 戻る 整数.parseInt(res.toString());
  21. }
  22. }

パイソン:

  1. クラスソリューション:
  2. def monotoneIncreasingDigits(self, n: int ) -> int :
  3. a = リスト(str(n))
  4. iが範囲(len(a)-1,0,-1)内にある場合:
  5. int (a[i]) < int (a[i-1])の場合:
  6. a[i-1] = str( int (a[i-1]) - 1) です。
  7. a[i:] = '9' * (len(a) - i) #pythonはフラグ値を設定する必要はなく、長さに応じて9を与えるだけです
  8. 戻る  int ( "" . join (a))

行く

  1. func monotoneIncreasingDigits(N int ) int {
  2. s := strconv.Itoa(N) //添え字を使いやすくするために数値を文字列に変換する
  3. ss := []byte(s) //簡単に変更できるように文字列をバイト配列に変換します。
  4. n := 長さ(ss)
  5. n <= 1の場合{
  6. Nを返す
  7. }
  8. i:=n-1; i>0; i -- {  
  9. if ss[i-1] > ss[i]{//前の桁が次の桁より大きいので、前の桁を1減らし、次の桁をすべて9に設定します。
  10. ss[i-1] -= 1
  11. j := i ; j < n; j++の場合、後続の数字はすべて 9 に設定されます。
  12. ss[j] = '9'  
  13. }
  14. }
  15. }
  16. res, _ := strconv.Atoi(文字列(ss))
  17. 戻り
  18. }

ジャバスクリプト

  1. var monotoneIncreasingDigits =関数(n) {
  2. n = n.toString()
  3. n = n.split( '' ).map(item => {
  4. 戻る+アイテム
  5. })
  6. フラグ = 無限大
  7. (i = n.length - 1; i > 0; i --)の場合{  
  8. n[i - 1] > n[i]の場合{
  9. フラグ = i
  10. n[i - 1] = n[i - 1] - 1
  11. 9 は
  12. }
  13. }
  14.  
  15. (i = flag; i < n.length; i++)の場合{
  16. 9 は
  17. }
  18.  
  19. n = n.join ( '' )
  20. 戻る+n
  21. };

<<:  1.2兆パラメータ:Googleの汎用スパース言語モデルGLaM、小サンプル学習がGPT-3を上回る

>>:  自動運転のジレンマと選択

ブログ    

推薦する

マスク氏は世界一の富豪の称号を失い、4000億ドルの高額報酬計画は却下され、テスラの登録地をテキサスに変更する予定

マスク氏は怒り、残酷なことを言った。 決してデラウェア州に法人を登録しないでください。 州裁判所はテ...

ゴールドマン・サックスはAIGCの徹底的な試験を計画的に実施している

AI を取り巻く大騒ぎを考えると、フォーチュン 500 企業が必死になって LLM を実用化し、アメ...

30歳以下の人はどこへ行ってしまったのでしょうか? OpenAIは若者を引き付けるために懸命に努力している

編纂者:ヤン・ジェン制作:51CTO テクノロジースタック(WeChat ID:blog)ビル・ゲイ...

今週の Github の人気プロジェクトの概要: 自然言語処理 Python ライブラリ spaCy が最もホットです!

先週、Github で最も人気のあるプロジェクトは、最近バージョン 2.0 に更新された自然言語処理...

研究者はディープラーニングを使用して巡回セールスマン問題を解決する上でどの程度進歩しましたか?

組合せ最適化問題の背景組み合わせ最適化は、NP 困難な制約付き最適化問題を解決することを目的とした、...

AIの力を借りれば、罠だらけのジムは歴史の舞台から消えるのでしょうか?

[[336650]]驚くべきことに、COVID-19の世界的大流行の中で、フィットネスやエクササイ...

COVID-19 最新情報: COVID-19 との戦いに役立つトップ 10 のイノベーション

[[320870]]迅速な感染検査から3Dプリントソリューションまで、世界中のテクノロジー企業が協力...

...

ワシントンポスト紙の李開復氏のコラム:お金を与えることでAI失業危機は解決するのか?シリコンバレーの大物は世間知らずすぎる

AI革命が到来し、それは最良の時代になるかもしれないし、最悪の時代になるかもしれない。それが良いこと...

ロシアメディア:人工知能は顔認識技術を使って宗教的傾向を判断できる

ロシア新聞は1月19日、「もう隠せないのか?」と題する記事を掲載し、米スタンフォード大学の学者マイケ...

...

...

ケーススタディ | 埋め込みに基づく特徴セキュアな計算

[[331789]]序文従来のデータの公開と共有の方法の多くは、生のデータをプレーンテキストで直接出...

顔認識の急速な発展は落ち着くはずだ

[[283549]] Xipo/Textいつから始まったのかは分かりませんが、顔認証が普及し、「顔認...