LeetCode :. 2は、一緒に問題解決のアルゴリズムの最適化のアイデア2つの数値を報告します

タイトル接続:2.二つの数字を追加します

問題の意味

ラベルされた被写体の難しさ中等を理解することの難しさ、そして質問の意味に必要な基本的なデータ構造のリストの一部として。

子供用の靴のチェーンが荒いBaiduの百科事典が本を引き出しに見えるかのデータ構造を見ることができます知ってはいけない、リストを説明するために少し平易な言葉はこれです:オンラインおよびオフライン

彼らも知らない、組立ラインオフあなたのオンラインを知っているが、組立ラインオフ組立ラインをオフに知らない人彼らのオンラインはい。

これは、片方向リンクリスト

質問の意味のこの質問は、各ノードが数字を格納し、ある双方向リンクリスト、に二つの数字であるセーブ逆転されるストレージ、。

問題解決のためのアイデア

まずは、異なる状況と対応する場合について考えてみましょう:

  1. 2に等しい鎖長。

入力:(2 - > 4 - > 3)+(5 - > 6 - > 4)
出力:(7 - > 0 - > 8)

  1. 長さの異なる二つのリスト。

入力:(2 - > 4)+(5 - > 6 - > 4)
出力:(7 - > 5 - > 0)

  1. 最終結果の最高レベルの存在を運びます。

入力:(2 - > 4 - > 5)+(5 - > 6 - > 4)
出力:(7 - > 0 - > 0 - > 1)

キー問題解決には、次のとおりです。マージリストを、それが確実に権利を運びます

アナログキャリー

まず、我々は少しを合計し、各ビット処理、フル運ぶために10進みます1

コード:

    public class Solution
    {
        public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
        {
            ListNode first = null;
            ListNode current = null;
            IList<int> sums = new List<int>();
            int sum = 0;
            int res = 0;

            while (l1 != null || l2 != null)
            {
                sum = res;
                if (l1 != null)
                {
                    sum += l1.val;
                    l1 = l1.next;
                }

                if (l2 != null)
                {
                    sum += l2.val;
                    l2 = l2.next;
                }

                res = sum / 10;
                sum %= 10;
                sums.Add(sum);
            }

            if(res > 0) sums.Add(res);

            if(sums.Any()) first = new ListNode(sums[0]);

            current = first;

            for (int i = 1; i < sums.Count; i++)
            {
                current.next = new ListNode(sums[i]);
                current = current.next;
            }

            return first;
        }
    }

実行する場合:252ミリ秒は、提出するC#ですべてのユーザーの13.33パーセントを打つ
メモリ消費を:26.7メガバイトを

これはの底部近く、少し惨めかかります。また、最適化の余地がまだあることを示しています。

定数の最適化

サイクリング時に我々が使用する上で、どこ我々は、事前にそれを保存することができます。IListCount

コードは以下の通りであります:

    public class Solution
    {
        public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
        {
            ListNode first = null;
            ListNode current = null;
            IList<int> sums = new List<int>();
            int sum = 0;
            int res = 0;
            int count = 0;

            while (l1 != null || l2 != null)
            {
                sum = res;
                if (l1 != null)
                {
                    sum += l1.val;
                    l1 = l1.next;
                }

                if (l2 != null)
                {
                    sum += l2.val;
                    l2 = l2.next;
                }

                res = sum / 10;
                sum %= 10;
                sums.Add(sum);
            }

            if (res > 0) sums.Add(res);

            count = sums.Count;

            if (count > 0) first = new ListNode(sums[0]);

            current = first;

            for (int i = 1; i < count; i++)
            {
                current.next = new ListNode(sums[i]);
                current = current.next;
            }

            return first;
        }
    }

実行する場合:164ミリ秒は、提出するC#ですべてのユーザーの85.62パーセントを打つ
メモリ消費を:26.8メガバイトを

ただ、変数を置き換え、それがほとんどで、実行を最適化し100、MS!これ100以上のMS 70%提出。

フロントとは、ほぼ15%最適化の余地があることを示しています。

サイクル数の最適化

アルゴリズムの上に記載のランダウの記号ケースの複雑さを計算するために、その複雑である:O(max(l1.Length, l2.Length))次に何が合理化されO(n)、単位重量サイクルの範囲こと、。

しかし、本当の複雑さは(も、サイクル内の操作の推定数は、ここに来るだけでループを忘れるとは考えられない)です2 * max(l1.Length, l2.Length) + 1ここでは、実際には2つのループを使用しているため。その後、我々はの複雑さのこの表現を使用することができ、複数の2削除するには、それが唯一の再循環です。

コードは以下の通りであります:

    public class Solution
    {
        public ListNode AddTwoNumbers(ListNode l1, ListNode l2)
        {
            ListNode first = null;
            ListNode current = null;
            int sum = 0;
            int res = 0;

            while (l1 != null || l2 != null)
            {
                sum = res;
                if (l1 != null)
                {
                    sum += l1.val;
                    l1 = l1.next;
                }

                if (l2 != null)
                {
                    sum += l2.val;
                    l2 = l2.next;
                }

                res = sum / 10;
                sum %= 10;

                if (current == null)
                {
                    first = new ListNode(sum);
                    current = first;
                }
                else
                {
                    current.next = new ListNode(sum);
                    current = current.next;
                }
            }

            if (res > 0) current.next = new ListNode(res);

            return first;
        }
    }

実行する場合:136ミリ秒は、提出するC#ですべてのユーザーの98.85パーセントを打つ
メモリ消費を:26.5メガバイトを

我々は、の最適化を実施し、重い秋のサイクルを取り除いた後20で、マルチMS(なぜほぼ半分の時間のために最適化されていない?)、20それはしているよりも、ミリ秒以上に13%提出しました。

Leetcodeは、時間のかかるの質問を熟考するために宣告します

二つの連続する道路の主題では最高(少なくとも第一到達する方法がない1%場合に)、そして羽が今日ここに書いた場合は、特に時間のかかる最短コード(ビットを参照し104、結果はMS)は、ダウンコピー後に直接提出しますそれは248、MS!??

結果を提出した後、再びその示し160ミリ秒を!??

同じコード、プラスまたはマイナスビットは大きすぎるの範囲!羽は助けるが、考えることができない場合はLeetCodeどのように判断コア問題があるタイミングの。破壊することができます達している。このフローティング・レンジランキング公平性の程度は、多分一部の人は思うだろうという人騒がせ羽、誇張された場合。

事実である:それは公正の範囲に破壊されました!このクラスは、オンラインと自動的に実際にコード入力例を実行すると、中のシステムよりも結果に非常に早く浮上している情報のコンテストACM大学対抗プログラミングコンテストは、一般に呼ばれるOJ(Online Judge System)オンライン裁判官。競技場では、ギャップが到達した160意味をミリ秒?これは、両チームの選手ということと同時に、または少しでも、後でコードを提出指し、そして最終的にトップにランク人が持っている運命に耳を傾けます

競争の観点にもかかわらず、このような大規模な浮動ランキングは、ある程度、客観的アルゴリズムの同様の時間複雑さのメリットを評価することができませんでした。アルゴリズムは、それが再び最後までそこにルーティングすることができる最初の実行をランク付けしました。

しかし、まだ続けることができる最適化アルゴリズム、停止線やコードのアイデアは〜よりは(本当に実現所有したい最適化するOJのを!)

おすすめ

転載: www.cnblogs.com/By-ruoyu/p/11323293.html