2025.7.10

Paiza様より、「レベルアップ問題集 ソートメニュー応用編 タプルソート JAVA編」の考察

Paiza様より「レベルアップ問題集 ソートメニュー応用編 タプルソート Python3編」、を以前紹介しましたが、今回はJAVA編です。
再度問題文を確認します。

            整数 n, m, k と n 行 m 列の表 a が与えられます。以下の条件をすべて満たすように、 a を行単位でソートしてください。
            ・ a の k 列目が昇順になっている
            ・ a の k 列目の値が等しい 2 つの行では、 a の 1 列目の値が昇順になっている
            ・ a の k 列目 と a の 1 列目から i 列目までのすべての値が等しい 2 つの行では、 a の i + 1 列目の値が昇順になっている ( 1 ≦ i ≦ m - 1 )
            
プログラミングで配列やlistをソートする機会は頻繁にあり、Pythonでソートするのは便利なsort()があり、そんなに難しくありません。
これがJAVAですと。簡単じゃありません。
2次元配列のソートはComparatorとかComparableとか、なんだか難しく、結局私には良くは理解できません。

さて、現在Googleでプログラミングに関する検索をすると、Google様のAIがサンプルコードを提示してくれることがあります。
こうなるとPaiza様のビジネスモデルの根幹を揺るがす事ですが、余計なお世話ですね。

で、そのAI様の提示してくださったコードを参考にして、この問題に適応できるように改造したコードで問題を通過できたので、参考までに公開します。
しかしながら100%意味を理解できないので、すべてを説明できませんが、私が理解できた部分は説明を入れました。
            
import java.util.*;


public class Main {
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int k = sc.nextInt();
        Integer[][] a = new Integer[n][m];
        
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                a[i][j] = sc.nextInt();
            }
        }
        // ここまでは標準入力
        Comparator<Integer[]> comparator = new Comparator<Integer[]>() {
            @Override               //Comparatorをインスタンス化し匿名classでcompareをオーバーライド
            public int compare(Integer[] i1, Integer[] i2) {
                
                int result = 0;
                int j = k-1;                //最初k番目をソートするのでjをk-1で初期化
                
                while(j<m && result==0){             //jをm列以下、かつ、resultが0のとき、真
                    
                    result = i1[j]-i2[j];               //列が同値のときはresultは0になる
                    if(j==k-1){             //jがk-1(k番目)の時は、jを0(列の1番目)にする
                        j = 0;
                    }else if(j==k-2){               //jがk-2(k-1番目)の時は、jに2(k番目は比較済なので飛ばす)を加える
                        j += 2;
                    }else{              //上記以外はjを1進める
                        j++;
                    }
                    
                }
                
                return result;
                
            }
        };
        
        Arrays.sort(a, comparator);                 //aをComparatorでソートする
        
        for (Integer[] row : a) {
            for(int i=0; i<m-1; i++){
                System.out.print(row[i]+" ");
            }
            System.out.println(row[m-1]);
        }               //標準出力
    }
}
            
            
尚、降順にしたい場合はresultを以下のようにします。
 result = i2[j]-i1[j];
また、単に列の1番目からソートする時はComparatorを以下のようにします。
            
Comparator<Integer[]> comparator = new Comparator<Integer[]>() {
    @Override
    public int compare(Integer[] i1, Integer[] i2) {
                
        int result = 0;
        int j = 0;
                    
        while(j<m && result==0){
                        
            result = i1[j]-i2[j];
            j++;
                                
        }
                    
        return result;
    
    }
};
            
            
もし、k番目だけをソートしたいときは、Comparatorをインスタンス化せず、以下の書き方でソートすると良いでしょう。
            

Arrays.sort(a, (i1, i2) -> i1[k-1] - i2[k-1]);