【ITニュース解説】Day 1 of 100 days dsa coding challenge
2025年10月02日に「Dev.to」が公開したITニュース「Day 1 of 100 days dsa coding challenge」について初心者にもわかりやすく解説しています。
ITニュース概要
「100日間DSAコーディングチャレンジ」が始まり、毎日GeeksforGeeksの課題を解き、問題解決とコーディングスキルの向上を目指す。初日は「Unique K-Number Sum」問題に挑戦。これは1~9の数字からk個選び合計がnになる組み合わせを探すもので、再帰的に可能性を探索するバックトラック法を用いた解法を解説している。
ITニュース解説
今回の記事は、「100日間データ構造とアルゴリズム(DSA)コーディングチャレンジ」の初日を紹介している。これは、プログラミングスキルを向上させるための個人的な挑戦であり、毎日GeeksforGeeksというプログラミング学習サイトの「今日の問題」(Problem Of The Day, POTD)を解き、その解決策を共有するというものだ。この挑戦の主な目的は、問題解決スキルを研ぎ澄まし、コーディング能力を一段と引き上げ、そして毎日新しい知識を習得することにある。システムエンジニアを目指す上で、このような継続的な学習と実践は非常に重要となる。
データ構造とアルゴリズム(DSA)とは、コンピュータプログラムがデータを効率的に処理・管理するための仕組みと手順を学ぶ学問分野である。データ構造はデータを格納する方法を指し、例えばリストや配列、木構造などがある。アルゴリズムは問題を解決するための手順や計算方法を指す。システムエンジニアにとって、DSAの知識は、複雑な問題を効率的に解決する能力を養い、パフォーマンスの高いソフトウェアを開発するために不可欠な基礎となる。どのようなプログラムを開発するにしても、その裏側では適切なデータ構造と効率的なアルゴリズムが選択されているため、この分野の理解はプログラマーとしての成長に直結する。
初日に取り組む問題は「Combination Sum III」というもので、難易度は「Medium」とされている。この問題の目的は、整数nと整数kが与えられたときに、以下の条件を満たすk個の数字の組み合わせを全て見つけることである。一つ目の条件は、使用できる数字が1から9の範囲に限定されることだ。二つ目の条件は、各数字は最大で一度しか使用できないことである。つまり、同じ数字を複数回使うことは許されない。そして、重要な条件として、選ばれたk個の数字の合計がちょうどnになる必要がある。出力は、条件を満たす数字の組み合わせのリストとなる。
具体的な例で見てみよう。もし入力がn=9, k=3だった場合、出力は[[1, 2, 6], [1, 3, 5], [2, 3, 4]]となる。これは、1から9の異なる数字を3つ選び、その合計が9になる組み合わせが[1, 2, 6]、[1, 3, 5]、[2, 3, 4]の3つあることを示している。例えば、[1, 2, 6]は1 + 2 + 6 = 9であり、3つの異なる数字が1から9の範囲で使われている。別の例として、入力がn=3, k=3だった場合は、出力は空のリスト[]となる。これは、1から9の異なる数字を3つ選んで合計を3にすることが不可能だからである。最小の異なる3つの数字は1, 2, 3であり、それらの合計は1 + 2 + 3 = 6となるため、合計が3になる組み合わせは存在しない。これらの制約として、nは1から50、kは1から9の範囲で与えられる。
この問題を解決するために提示されているのは、「バックトラッキング」というアルゴリズム手法を用いたPythonコードである。バックトラッキングとは、問題の解を探す際に、可能性のある選択肢を一つずつ試していき、もしその選択肢が最終的に解に繋がらないとわかったら、元の状態に戻って(バックトラックして)別の選択肢を試す、という方法である。これは、迷路の探索に例えられることが多い。
コードでは、combinationSumというメイン関数の中にbacktrackという再帰関数が定義されている。resは最終的な結果を格納するリストである。backtrack関数は三つの引数を持つ。startは次に探索を開始する数字の候補の最小値、pathは現在までに選んだ数字のリスト、totalはpathに含まれる数字の合計をそれぞれ表す。
まず、backtrack関数には二つの終了条件(ベースケース)がある。一つ目はif len(path) == k and total == n:という条件で、もしpathの長さがちょうどkになり、かつpathの合計がちょうどnになった場合、それは有効な組み合わせが見つかったことを意味する。このとき、現在のpathを結果リストresに追加し、この再帰のパスは終了する。二つ目の終了条件はif len(path) >= k or total > n:というもので、もしpathの長さがk以上になってしまった場合(つまり、すでにk個の数字を選んでしまったか、それ以上選びすぎた場合)か、あるいは現在の合計totalが目標のnを超えてしまった場合、そのパスはもう有効な組み合わせに繋がらないので、すぐに処理を終了する。これにより、無駄な探索を省くことができる。
これらの終了条件が満たされない場合、関数は次の数字を探すためのループ処理に入る。for i in range(start, 10):というループは、startから9までの数字(10は含まれないため)を順番に試すことを意味する。startを使うことで、同じ数字を重複して選ぶことを防ぎ、また、組み合わせの順序を考慮しない(例えば[1, 2, 6]と[2, 1, 6]を同じ組み合わせとみなす)ようにしている。具体的には、次の数字を選ぶ際には、現在のiより大きい数字のみを考慮することで、[1, 2, 6]を選んだ後に[2, 1, 6]のような重複した組み合わせを生成することを避ける。
ループの中で、backtrack(i + 1, path + [i], total + i)という再帰呼び出しが行われる。これは、現在の数字iをpathに追加し、totalをiだけ増やして、次の数字をi + 1から探し始める、という意味である。path + [i]という書き方は、現在のpathリストにiを追加した新しいリストを作成し、それを次の呼び出しに渡している。これにより、元のpathが変更されることなく、異なる探索パスが独立して進められる。
最後に、backtrack(1, [], 0)という初期呼び出しから探索が始まる。これは、最初の数字を1から探し始め、初期のpathは空のリスト、合計は0であることを意味する。すべての探索が完了すると、resリストに集められた有効な組み合わせのリストが返される。
このようなコーディングチャレンジに日々取り組むことは、システムエンジニアとしてのキャリアを築く上で非常に有益だ。毎日新しい問題に挑戦し、それを解決するための最適なデータ構造やアルゴリズムを考えることで、論理的思考力と問題解決能力が飛躍的に向上する。また、提示された解決策を理解し、それを自分の手で実装してみることで、理論と実践を結びつける貴重な経験を積むことができる。単に知識を詰め込むだけでなく、実際に手を動かしてコードを書くことで、より深く、より実用的なスキルが身につくのだ。この挑戦は、システムエンジニアとして成長するための地道だが確実な一歩となる。