LoginSignup
1
9

More than 3 years have passed since last update.

Javaアルゴリズム問題を解いてみた(基礎問題)

Last updated at Posted at 2020-02-11

だいぶ古い記事ですが、CodeZineの過去の連載で
「脱 超初心者 Javaアルゴリズム問題集」というものをみつけました。
https://codezine.jp/article/corner/58
記事によると、「プログラム経験が3ヶ月もあれば十分解くことができるでしょう。」
という難易度らしいので、今の自分にはちょうどよいと思いました。
4問しか記事が見つけられませんでしたが、基礎を復習する意味で時間も意識して実施しています。

以下、問題文を引用させていただいてます。
正答例は記事で御覧ください。
脱 超初心者 Javaアルゴリズム問題集
https://codezine.jp/article/corner/58

第1回 条件分岐と永久ループ

標準入力された値があればそのまま表示、値がなければエラーメッセージを表示するプログラムを作成してください。なお、「EXIT」が入力されるまで、処理を繰り返し続けるものとします。

所要時間目安  A:30分 B:60分 C:120分(A:(開発歴)2年以上、B:1年程度、C:3ヶ月程度を目安)

コマンドラインに入力を待ち受けるための「>」を表示する。
「EXIT」が入力された時点でプログラムを終了する。それ以外が入力された場合は「未入力です」と表示して、再び入力待ち受け状態にする。

キーワード

if文の使用法を習得する。
while()/for(;;)による永久ループの使用法を習得する。

ポイント

標準入力からの入力を受け取るストリームはSystemクラスのフィールドinよりInputStreamクラスのインスタンスとして取得できる。
永久ループは次のようにすることによって表すことができる。

    public static void main(String[] args) {
        question1();
    }

    public static void question1() throws IOException {
        System.out.print(">");
        InputStreamReader writeConsole = new InputStreamReader(System.in);
        BufferedReader buffer = new BufferedReader(writeConsole);
        String writeString = buffer.readLine();
        while (true) {
            if (writeString.equals("")) {
                System.out.println("未入力です");
            } else {
                System.out.println(writeString);
            }
            System.out.print(">");
            writeString = buffer.readLine();
            if (writeString.equals("EXIT")) {
                System.exit(0);
            }
        }
    }

永久ループの手法、InputStreamReaderを使った入力を知られて勉強になった。

第2回 条件分岐(複合条件)

標準入力された月、日が、今日であるかどうかを判定するプログラムを作成してください。

所要時間目安  A:30分 B:60分 C:120分(A:(開発歴)2年以上、B:1年程度、C:3ヶ月程度を目安)

コマンドラインに「今日は何月何日でしょう?」のメッセージを表示する。
それぞれ、「何月?==> 」「何日? ==> 」を表示して入力を受け取る。
入力された月日が今日であれば「正解!!」、間違っていれば「間違っています」と表示する。

キーワード

if文における複合条件の使用方法を習得する。

ポイント

日付の取得は、Calendarクラスを用いて行う。通常のクラスのようにコンストラクタをnewせずgetInstance()メソッドを呼び出してインスタンスを取得する。
標準入力は、Int型で受け取る。
if文は1度しか使用しない。

    public static void main(String[] args) {
        question2();
    }

    public static void question2() throws IOException {
        System.out.println("今日は何月何日でしょう?");
        int rightNowMonth = Calendar.getInstance().get(Calendar.MONTH) + 1;
        int rightNowDate = Calendar.getInstance().get(Calendar.DATE);
        BufferedReader buffer1 = new BufferedReader(new InputStreamReader(System.in));

        System.out.print("何月?==>");
        int writeMonth = Integer.parseInt(buffer1.readLine());
        System.out.print("何日?==>");
        BufferedReader buffer2 = new BufferedReader(new InputStreamReader(System.in));
        int writeDate = Integer.parseInt(buffer2.readLine());
        if (rightNowMonth == writeMonth && rightNowDate == writeDate) {
            System.out.println("正解!!");
        } else {
            System.out.println("間違っています");
        }
    }

日付の扱いについての理解が深まった。

第3回 ループ

標準入力から、n個の年齢を受け取り、その平均年齢を算出するプログラムを作成してください。年齢はコマンドライン引数から取得するものとします。

所要時間目安  A:20分 B:40分 C:90分(A:(開発歴)2年以上、B:1年程度、C:3ヶ月程度を目安)

年齢は、コマンドライン引数から取得する。
コマンドライン引数が指定されていない場合は「引数に年齢を指定してください」のメッセージを表示する。

キーワード

for文を使い、n個のループ処理を理解する。
入力チェックを理解する。

ポイント

コマンドライン引数はmain()メソッドにStringの配列型として引き渡される。

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("引数に年齢を指定してください");
        } else {
            int sumAge = 0;
            for (String age : args) {
                sumAge += Integer.parseInt(age);
            }
            int averageAge = sumAge / args.length;
            System.out.println("平均年齢は " + averageAge + " 歳です");
        }
    }

コマンドライン引数を扱うことが少なかったので、良い経験になった。

第4回 多重ループと二次元配列

掛け算九九表を出力するプログラムを作成してください。

所要時間目安  A:30分 B:50分 C:100分(開発歴)2年以上、B:1年程度、C:3ヶ月程度を目安)

二次元配列を作成して、九九データの代入を行い、その後の表示は分けて作成する。
ヘッダー、フッタ及び、列ヘッダー(段の表示)は、省いても構いません。

キーワード

for文を使った多重ループ処理を理解する。
二次元配列への代入、参照を理解する。

ポイント

数字を桁をそろえて出力するにはDecimalFormatクラスを使用する。0詰め2桁で出力するにはnewするときにコンストラクタに"00"を渡す。

public static void main(String[] args) {
        System.out.println("+--------- かけ算九九表 --------+");
        System.out.println("|     1  2  3  4  5  6  7  8  9 |");
        System.out.println("|  +----------------------------|");
        int h = 1;
        for (int[] list : question4()) {
            // List<Integer>を利用する場合は以下
            // for (List<Integer> list : question4_2()) {
            System.out.print("| " + h++ + "|");
            for (int value : list) {
                if (value < 10) {
                    System.out.print(" 0" + value);
                } else {
                    System.out.print(" " + value);
                }
            }
            System.out.print(" |\n");
        }
        System.out.println("+--+----------------------------+");
    }
    //配列を使用
    public static int[][] question4() {
        int[][] list = new int[9][9];
        for (int outer = 0; outer < 9; outer++) {
            int[] value = new int[9];
            for (int inner = 0; inner < 9; inner++) {
                value[inner] = (outer + 1) * (inner + 1);
            }
            list[outer] = value;
        }
        return list;
    }
    //Listを使用
    public static List<List<Integer>> question4_2() {
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        for (int outer = 1; outer <= 9; outer++) {
            List<Integer> value = new ArrayList<Integer>();
            for (int inner = 1; inner <= 9; inner++) {
                value.add(outer * inner);
            }
            list.add(value);
        }
        return list;
    }

出力結果の見た目までこだわって実装したので楽しかった。

すべての問題を1問あたり1時間以内に解答でき、楽しめました。
4問目の2次元配列の問題は、Listと配列両方の実装方法を解答しています。
それぞれの違いは、要素数が固定か否かくらいしか理解してませんでしたが、改めて調べると、データへのアクセス方法が異なるため、処理速度に違いがあるらしいことがわかりました。

要素へのアクセス 要素の追加
配列 高速 低速
List 低速 高速
1
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
9