ログイン新規登録
Qiita Conference2024年4月17日水曜日から19日金曜日16時半から

Qiita最大規模のテックカンファレンス参加申し込み受付中!

基調講演ゲスト(敬称略)

牛尾剛、 市谷聡啓、 けんすう、 ゆる言語学ラジオ、 田中邦裕、小城久美子、 飯沼亜紀

0

【終了コード9】ABC079 B - Lucas Number のTLE問題(C++, 配列と再帰関数の処理速度の違い)

投稿日

Atcoder公式のC++教材、AtCoder Programming Guide for beginners (APG4b)に取り組んでいるのですが、3章の最初の演習問題で躓いたので共有します。

ABC079 B問題「Lucas Number」 とは

chatGPTに聞いてみたルカ数について。
一言でまとめると、初項が2で2番目の項が1のフィボナッチ数列です。

ルカ数列は、数学の世界で見られる興味深いパターンの一つです。この数列は、2つの初期値を持ち、その後の各項は直前の2つの項の和として生成されます。
最初の2つの項が2と1であるとき、次の項はそれらの和であり、その後も同様に続きます。つまり、数列は次のように始まります:2, 1, 3, 4, 7, 11, 18, 29, 47, ..

【間違えた回答】再帰関数(C++)

最初問題を読んだ時、「お、これはPiscineでもやったアレではないか!」と再帰関数に飛びつきました。しかし実行してみると終了コード9(TLE)、、実行に時間がかかりすぎていると怒られてしまいました。

#include <iostream>
using namespace std;

int ft_lucas(int64_t N)
{
	if (N == 0)
		return 2;
	if (N == 1)
		return 1;
	return (ft_lucas(N - 1) + ft_lucas(N - 2));
}

int main(void)
{
	int64_t N;
	cin >> N;
	int64_t ans = 0;
	ans = ft_lucas(N);
	cout << ans << endl;
	return 0;
}

【正解になった回答】配列(C++)

色々調べた結果、再帰関数はループよりは早いものの、配列に1つずつ要素をメモしておく処理よりは数倍遅いことがわかりました。

理由は明確で、ft_lucas(N-1)とft_lucas(N-2)からの呼び出しで複数回おなじ関数が呼び出されるため、より大きな項の数を求める場合には重複した計算が指数関数的に増えていきます。再帰が深くなればなるほどスタックに多数のフレームが重なり、スタックオーバーヘッドが起こるリスクも高くなります。

しかし配列を使用した場合は、計算結果を都度格納していくため。重複計算を防ぐことが可能になります。再計算が不要になり、処理時間が大幅に削減されることに繋がります。

#include <iostream>
#include <vector>
using namespace std;

int main(void)
{
	int64_t N;
	cin >> N;
	vector<int64_t> lucasnum(N + 1);
	lucasnum.at(0) = 2;
	lucasnum.at(1) = 1;
	for (int i = 2; i <= N; i++)
	{
		lucasnum.at(i) = lucasnum.at(i - 1) + lucasnum.at(i - 2);
	}
	cout << lucasnum.at(N) << endl;
	return 0;
}

実際に二つのコードの実行時間の差は歴然でした、、
(下側が再帰関数によるもの、上側が配列によるもの)

Screenshot 2024-04-03 at 11.49.00.png

まとめ

再帰関数の方がスタイリッシュに記述できるので飛びつきがちでしたが、その都度適切なアルゴリズム・データ構造を利用できるように精進したいですね。

引き続き楽しいAtcoderライフを!

新規登録して、もっと便利にQiitaを使ってみよう

  1. あなたにマッチした記事をお届けします
  2. 便利な情報をあとで効率的に読み返せます
  3. ダークテーマを利用できます
ログインすると使える機能について

コメント

この記事にコメントはありません。

いいね以上の気持ちはコメントで

Qiita Conference 2024 4月17日(水)~19(金)開催!

Qiita Conferenceは、Qiita最大規模のテックカンファレンスです!

基調講演ゲスト(敬称略)

牛尾剛、 市谷聡啓、 けんすう、 ゆる言語学ラジオ、 田中邦裕、小城久美子、 飯沼亜紀

記事投稿キャンペーン開催中

Qiita×Findy記事投稿キャンペーン 「今の開発組織でトライしたこと・トライしていること・トライしようとしていること」

~
詳細を見る
0

新規登録して、Qiitaをもっと便利に使ってみませんか

この機能を利用するにはログインする必要があります。ログインするとさらに下記の機能が使えます。

  1. ユーザーやタグのフォロー機能であなたにマッチした記事をお届け
  2. ストック機能で便利な情報を後から効率的に読み返せる

ソーシャルアカウントでログイン・新規登録

メールアドレスでログイン・新規登録