アルゴリズムチュートリアル1:ダイヤモンドと石

アルゴリズム設計が何であるかをした後、学習アルゴリズムの設計を学んでいます。強力なアルゴリズムの有効な手段として、熟練した職人によって、それは訓練で、日常や仕事の問題点、研修で質問を磨くためのイニシアチブをとる、別の訓練です。

ここではブラシ対象leetcodeだ、アルゴリズムは、ウェブサイトのアドレスを答えることができleecodeです:https://leetcode.com/、ない長い前に中国語版、アドレスは次のとおりです。https://leetcode-cn.com/

今回、話題に最初:
ダイヤモンドと石

この問題のために、自然のアイデアは、Sの文字Jの出現数を決定するために、つまり、質問の意味に従うことです あなたが決めることができればJの数は、すべての文字が判断することができることを、手紙に登場 - 再利用可能なルーチンが出てきました。

そのため、自然な考え方によると、手紙はJの数は、標準的な作業であると判断された表示され、「リユース」、日常的には、小さな道を使用する前には、各文字の数が加算表示され、数回を述べ、問題があることができを取り除くために。

しかし、アイデアの一般的な性質は、効率的なアルゴリズムではありません。

このトピックでは、単に問題を解決するためのルーチンの「リユース」を適用しないでください、あなたは、より効率的な設計を考える必要があります。

優れたアルゴリズムを設計するには、最初に適切なデータ構造を設計または選択する場合があります。蚊を戦うために木を伐採ナイフ、または大砲は、不適切な、しかし鉱山不適切な武器素手なしです。ルーチンは、最初に武器を取得するには、問題を解決するために、あります。

この記事では、特定のデータ構造の問題を解決するために設計された基本的なアルゴリズム設計ルーチンを、説明しています。どこでもこのルーチンは、。データ構造を設計するためのアルゴリズムを設計するために。データ構造は、あること、データの組織構造は、組織が独自の特性を持っている必要があります。

この問題については、このルーチンの使用は、それは、どのように迅速に(文字のSとペアではなく、一つ一つ、)それが所有して表示された回数を知るために手紙Jを行うために、データ構造の種類を設計することですか?

Sの特性(文字のみ、大文字と小文字を区別)によれば、このようなデータ構造を設計することができ、場所を見つけることができるように、アレイは、アレイは、アルファベットのインデックス値で、すべての文字の値の長さをカバーすることができますそして、この位置の値は、文字が出現した回数です。

このような配列がある場合、インデックスの値の手紙に非常にシンプルで、文字Jの出現回数を調べるために、回数は、対応する値の登場です。

このような配列、どのように構築するには?

「Z」値+配列の長さとして1、プラス1配列インデックスが0から始まるために、「Z」は場所を見つけることができる指標でみましょう。

時の初期アレイは、各要素の値は0です。

次に、Sを横断開始、文字を直接+1の次に位置値位置に、インデックスされます。

Sを通過した後に、このデータ構造は、設定され、状態データ構造も構築され、それは以下のスクリーンショットに示すような、既に利用可能な状態である機械学習を介して同一の場合には、:
データ構造を構築

最後に、文字J、この手紙が表示された直接の数を横断する、優れた構造を構築するために、このデータを使用し、問題を解決することができます。

ここでは、データ構造を構築するための配列を設計し、これは単に説明するために、一例であり、ルーチン「データ構造を設計するために、」データ構造の種類に、そのことについてのように、選択肢を与えているように、また、文字Sキーによって表される、ハッシュテーブルを設計することができ、その値は、文字の出現回数である、と彼らはエレガントな問題を解決することができます。

特定のパフォーマンスが重要な課題となっていない限り、したがって、それは重要なルーチンではなく、具体的なパフォーマンスです。

上記、特定の問題に応じて、適切なデータ構造を構築する方法について説明し、焦点は意識を構築するためのデータ構造を持つことです。

最後に、二つの小さな方法は、この記事の主な内容のコードとleecodeフィードバックと終了を達成するために与えられました:

// c code
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int numJewelsInStones(char* J, char* S) {
    int arrlen = 'z'+1;
    char* arr = (char*)malloc(arrlen);
    memset(arr, 0, arrlen);
    for (int i = 0; i < strlen(S); i ++) {
        arr[S[i]] += 1; 
    }
    int cnt = 0;
    for (int j = 0; j < strlen(J); j ++) {
        cnt += arr[J[j]];
    }
    free(arr);
    return cnt;
}

int main(int argc, char *argv[])
{
    char *S = "aAAbbbb", *J = "aA";
    int cnt = numJewelsInStones(J, S);
    printf("cnt=%d\n", cnt);
    return 0;
}

上記leecodeに提出実装コードは、(主な理由は、より多くのスペースがあることを、提出され、100%のCコードを打つ、高速な実行速度)などのフィードバックを見ることができます:
leecodeフィードバック1

// c# code
public int NumJewelsInStones(string J, string S)
{
    int result = 0;

    if (string.IsNullOrEmpty(J) || string.IsNullOrEmpty(S)) return result;

    var kv = new Dictionary<string, int>();
    var sArr = S.ToArray();
    var jArr = J.ToArray();

    //S去重,统计字母出现次数
    int i = 0, v = 1;
    while (i < sArr.Count())
    {
        if (kv.ContainsKey(sArr[i].ToString()))
        {
            kv[sArr[i].ToString()] += v;
            i++;
            continue;
        }

        kv.Add(sArr[i].ToString(), v);
        i++;
    }

    //统计宝石数
    foreach (var kvp in kv)
    {
        if (!J.Contains(kvp.Key)) continue;

        result += kvp.Value;
    }

    return result;
}

次のように上記leecodeを達成するために提出され、フィードバックが得られます:
leetcodeフィードバック2

要約すると、この論文はつまり、問題を解決するために、データ構造を設計するために、定期的なルーチンのアルゴリズムの設計について説明します。あなたは問題が発生したとき、あなたは、自分で特定のデザインを少し時間を与えるべきである、とアルゴリズムの設計では、あなた自身に尋ねる必要があります:データ構造を設計する最初のではないでしょうか?


笑

おすすめ

転載: www.cnblogs.com/freeself/p/10945640.html