문 제

온라인 저지에 가입한 사람들의 나이와 이름이 가입한 순서대로 주어진다. 이때, 회원들을 나이가 증가하는 순으로, 나이가 같으면 먼저 가입한 사람이 앞에 오는 순서로 정렬하는 프로그램을 작성하시오.

입 력

첫째 줄에 온라인 저지 회원의 수 N이 주어진다. (1 ≤ N ≤ 100,000)

둘째 줄부터 N개의 줄에는 각 회원의 나이와 이름이 공백으로 구분되어 주어진다. 나이는 1보다 크거나 같으며, 200보다 작거나 같은 정수이고, 이름은 알파벳 대소문자로 이루어져 있고, 길이가 100보다 작거나 같은 문자열이다. 입력은 가입한 순서로 주어진다.

3
21 Junkyu
21 Dohyun
20 Sunyoung

출 력

첫째 줄부터 총 N개의 줄에 걸쳐 온라인 저지 회원을 나이 순, 나이가 같으면 가입한 순으로 한 줄에 한 명씩 나이와 이름을 공백으로 구분해 출력한다.

20 Sunyoung
21 Junkyu
21 Dohyun

코 드

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;

namespace Algorithm
{
    class Member
    {
        public int Age { get; set; }
        public string? Name { get; set; }
        public int Order { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            int N = int.Parse(ReadLine());

            List<Member> inputList = new List<Member>();

            for (int i = 0; i < N; i++)
            {
                string[] value = ReadLine().Split(' ');

                inputList.Add(new Member
                {
                    Age = int.Parse(value[0]),
                    Name = value[1],
                    Order = i
                });
            }

            var sortList = inputList.OrderBy(x => x.Age)
                                    .ThenBy(x => x.Order)
                                    .ToList();

            foreach (var member in sortList)
                WriteLine($"{member.Age} {member.Name}");
        }
    }
}

비교코드 - 1

소요시간 216ms, 내 코드보다 20배 감축…

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.IO;

namespace Algorithm
{
    class Member
    {
        public int Age { get; set; }
        public string? Name { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            int N = int.Parse(ReadLine());

            StreamWriter writer = new StreamWriter(OpenStandardOutput());

            var inputList = Enumerable.Range(0, N)
                                    .Select(_ =>
                                    {
                                        var values = ReadLine()?.Split(' ');
                                        return new Member
                                        {
                                            Age = int.Parse(values?[0] ?? "0"),
                                            Name = values?[1]
                                        };
                                    })
                                    .ToList();

            var sortList = inputList.OrderBy(x => x.Age).ToList();

            foreach (var member in sortList)
            {
                writer.WriteLine($"{member.Age} {member.Name}");
            }

            writer.Close();
        }
    }
}

공 부

Enumerable.Range

  1. 반복 데이터 채우기

소요시간 216ms, 내 코드보다 20배 감축…

// #1 LINQ 사용
int[] arr = Enumerable.Repeat(-1, 10).ToArray();

// #2
int[] arr = new int[10];
Array.Fill(arr, -1);
  1. 연속 데이터 채우기

소요시간 216ms, 내 코드보다 20배 감축…

// #1 List 활용
List<int> myList = new List<int>(10);       // 데이터 크기 10

for (int i = 0; i < myList.Count; i++)
    myList[i] = i;

// #2 Enumerable.Range 활용, LINQ 사용

List<int> myList = Enumerable.Range(0, 10).ToList(); // 0부터 10개를 채워라
int[] myArray = Enumerable.Range(0, 10).ToArray(); // 0부터 10개를 채워라

결론 : 단순 값 변경이라면 반복문을, 특정 컬렉션을 새로 생성하면서 값을 채워넣을 때는 Enumerable.Range(,)가 용이!

  1. OrderBy, ThenBy
    • OrderBy(x => x.Score) : Score를 기준으로 오름차순(디폴트)으로 정렬하겠다는 의미! 내림차순으로 정렬을 하고 싶다면 OrderBy 대신 OrderByDescending 사용!
    • ThenBy(x => x.Score) : ThenBy도 정렬할 때 사용! OrderBy와 차이가 있다면 OrderBy로 우선 정렬을 하고 차선으로 ThenBy**를 이용하여 정렬한다는 의미!

’?’ null 조건부 연산자

  • value가 null이 아니면 인덱스 ‘0’에 있는 요소에 액세스 한다라는 뜻! value 가 null인 경우 표현식은 ‘NullReferenceException’을 발생시키는 대신 ‘null’을 반환한다!

’??’ 널 병합 연산자

  • 왼쪽 값이 null인 경우 기본값을 제공한다 라는 뜻! 위 ‘비교코드 - 1’에서 values?[0] 값이 null인지 확인하고 인덱스[0]에서 값을 검색하여 값이 null인 경우 다음 “0”을 사용하겠다 라는 뜻이다!