記事ディレクトリ
14日間の読書チャレンジ * 努力は並大抵のものではありません~ アルゴリズムを学ぶ人は誰でも、桃源明の「桃花春」のように、アルゴリズムを解くための鍵が必要です。何十歩も歩くと突然陽気になる。」
アルゴリズムの知識ポイント
アルゴリズムの特徴
(1) 有限性: アルゴリズムは複数の命令から構成される有限なシーケンスであり、複数回実行されると必ず終了し、永遠に停止することは不可能です。
(2) 確実性: すべてのステートメントには、曖昧さのない明確な意味があります。
(3) 実現可能性:現在の環境では、限られた演算数でアルゴリズムを実現可能
(4) 入力/出力: 0 個以上の入力と 1 つ以上の出力があります。
アルゴリズムトピックの説明
シーケンスの合計を求めるアルゴリズムを作成します。
質問のアイデア
このトピックを見てどう思いますか? forループ? whileループ? まず for ループのコードを見てください。
for ループ ソリューション
int sum1 ( int n ) {
int sum= 0 ;
for ( int i= 1 ; i<= n; i++ )
sum+= pow ( - 1 , i) ;
return sum;
}
コピー
上記のコードは確かに合計演算を実現できますが、なぜそうではないのでしょうか?
別の書き方を見てみましょう。
誘導的解決策
int sum2 ( int n ) {
int sum= 0 ;
if ( n% 2 == 0 )
sum= 0 ;
else
sum= - 1 ;
return sum;
}
コピー
このコードを見た後、これがまだ可能であることに突然気づきましたか?これは数学者ガウスが使用したアルゴリズムではないでしょうか?
対数は合計 50 あり、各対数の合計は 101 であるため、合計は次のようになります。
(1+100)* 50 = 5050
1787 年、他の子供たちが半日かかったのに対し、10 歳のガウスは非常に短時間で結果を計算しました。 for ループを使用すると、n 回ループする必要があり、各ループで pow 演算が必要になり、加算演算が実行されることがわかります。 n = 10000 の場合、このようなプロセスを 10000 回計算します。 観察と帰納を通じて、2 番目の方法は 1 回だけ必要ですが、大きな違いはありますか?
ガウス法も知っていますが、同じような問題に遭遇したことがあります...私たちが使用している愚かな方法もアルゴリズムですか? 答え: はい
アルゴリズムの複雑さの計算
優れたアルゴリズムの基準
効率的 - 時間の複雑さ
低ストレージ - スペースの複雑さ
時間計算量の計算
アルゴリズムの実行に必要な時間。現代のコンピューターは 1 秒間に多くの計算を実行できるため、秒単位で測定することはできません。 同じコンピュータの 1 回の時間は比較的固定されており、構成が異なるコンピュータでは異なります。 したがって、実行回数を時間計算量とみなします。
int sum= 0 ;
int total= 0 ;
for ( int i= 1 ; i<= n; i++ ) {
sum= sum+ i;
for ( j= 1 ; j<= n; j++ )
total= total+ i* j;
}
コピー
上記すべてのステートメントの実行数を合計すると、次のようになります。
1 + 1 + n+1 + n + n×(n+1) + n×n 。
这个可以用一个函数T(n) 来表示: T(n) = 2n2+3n+3 当n足够大的时候,例如n = 105 ,那么T(n) = 2 * 1010 + 3 *105 +3 可以看出,算法运行的时间主要取决于最高项,小项和常数可以忽略不计。 有些算法,如排序,查找、插入算法等,可以分为最好 、最坏 和平均情况 分别去求算法的渐进复杂度。但是考察一个算法时,通常考察最坏的情况,最坏的情况对衡量算法好坏具有实际意义
空间复杂度的计算
算法占用的空间大小。 空间复杂度的本意指的是算法在运行过程中,占用了多少存储空间。算法占用的存储空间包括:
(1)输入、输出数据
(2)算法本身
(3)额外需要的辅助空间 输入输出占用的空间是必须的,算法本身占用的空间可以通过精简算法来缩减,但缩减的量是很小的,可以忽略不计。 算法在运行时候,所使用的辅助变量占用空间,才是衡量算法复杂度的关键因素。
常数变量复杂度
请分析如下的算法空间复杂度
void swap ( int x, int y ) {
int temp;
temp= x;
x= y;
y= temp;
}
复制
两个数交换的过程:
这里使用了temp辅助变量,空间复杂度为O(1)
递归空间复杂度
在递归算法中,每次递归都需要一个栈来保存调用记录,因此在计算递归的空间复杂度的时候,需要计算递归栈的深度。
int fac ( int n ) {
if ( n== 0 || n== 1 )
return 1 ;
else
return n* fac ( n- 1 ) ;
}
复制
阶乘是典型的递归调用问题,递归包括地推和回归。递推是将原问题不断分解成子问题,直至满足结束条件,返回最近子问题的解。然后逆向逐一回归,最终到达递推开始的原问题,返回原问题的解。
思考:试求5的阶乘,程序将怎么计算呢? 5的阶乘的递推和回归的过程如下:
上の2つの図にあるように、再帰と回帰の過程は論理的思考によって推論され、絵の形でグラフィカルに表現されていますが、コンピュータ内部ではどのように計算が行われているのでしょうか。 コンピュータでは「スタック」と呼ばれるデータ構造が使われています。「スタック」はお皿を入れる 容器 のようなもので、毎回上から入れる、取り出すときは上からしか取れず、挿入することもできません。または途中からの抽出はできないため、「後入れ先出し」と呼ばれます。
この図から、スタックのプッシュとポップのプロセスがわかります。サブ問題は、戻り値が直接解決できるようになるまで、最初にステップごとにスタックにプッシュされ、その後、スタックからステップごとにポップアウトされます。最後に戻り値を取得します。 操作中、n 個のスタックが補助空間として使用されるため、階乗再帰アルゴリズムの空間複雑さは O(n) です。 n の階乗は n-1 の階乗よりも乗算演算が 1 つ多いだけであるため、時間計算量も O(n) になります (fac(n) = n * fac(n-1))。 T(n) を使用して fac(n) の時間計算量を表す場合、T(n) = T(n) + 1 =T(n-1) + 1 + 1 ... = T と表すことができます。 (1) + ... 1 + 1 =n