모름

이번 문제에서 배우는 것은?

일단 반복문(Loops)를 사용하여 푸는 문제입니다. 그리고 이 퍼즐은 가장 간단한 해결책으론 충분한 성능이 나오지 않습니다. 그리고 우리는 거대한 배열을 다룰것이고 이 것을 처리하는 시간에 대한 경험을 얻을 수 있습니다.

 

Sorting, Lists를 사용할 수 있습니다.

 

문제 요약

스토리 : 경마장 주인이 두 마리 말이 듀얼로 경기하는 '듀얼'경기를 만듭니다. 이 경기를 흥미롭게 하기 위해선 가지고 있는 말 중 힘이 가장 비슷한 말 2마리를 쌍으로 붙여야합니다.

 

문제 : N마리의 말 중에서 가장 힘이 비슷한 두 마리의 말을 골라서 그 차이를 출력하는 프로그램을 만드시오.

 

문제 풀기

class Solution
{
    static void Main(string[] args)
    {
        int N = int.Parse(Console.ReadLine()); //N마리의 말 입력
        for (int i = 0; i < N; i++)
        {
            int pi = int.Parse(Console.ReadLine()); //N마리의 말 힘 입력
        }
        Console.WriteLine("answer"); //결과 출력
    }
}

베이스로 입력된 화면입니다. N마리의 말을 첫째줄에 입력받았고, 그 다음 줄에는 N번째에 해당하는 말의 힘을 입력받았습니다.

 

일단 생각나는데로 적어보자면, n마리의 말을 힘 별로 정렬시켜야합니다. 이어서 반복문을 통해 인덱스별로 차이값을 구해 제일 낮은 값을 저장합니다. 이때 해당인덱스가 몇번인지 기록합니다. 가장 낮은 값이 갱신되지 않으면 이 값을 가진 인덱스 2개를 힘이 가장 비슷한 말이라고 보면 됩니다.

 

이렇게 풀리는지 살펴보겠습니다.

 

using System;
using System.Linq;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;

//n마리를 힘대로 차례대로 나열한다
//루프를 통해 인덱스별로 차이값을 도출한다
//차이값이 최소인 인덱스 두 개를 고른다

class Solution {
    static void Main(string[] args)
    {
        int N = int.Parse(Console.ReadLine());      //N마리의 말
        List<int> horseList = new List<int>();          //N마리의 말을 보관할 LIst

        for (int i = 0; i < N; i++)
        {
            int pi = int.Parse(Console.ReadLine()); //말 한마리의 힘
            horseList.Add(pi);                      //List에 그대로 저장
        }

        SelectionSort(horseList);                   //선택정렬로 힘 별로 정렬

        int result = FindMinimumValue(horseList);   //제일 차이가 적은 값을 찾기
        Console.WriteLine(result);
    }

    ///////////////////////// 차이값을 구하는 코드
    static int FindDifferenceValue(List<int> list, int startIndex)
    {
        if (list.Count == 1) return list[0];

        int firstValue = list[startIndex];
        int minSub = Math.Abs(list[0] - list[1]);

        for (int i = startIndex + 1; i < list.Count; i++)
        {

            if (Math.Abs(firstValue - list[i]) < minSub)
            {
                minSub = Math.Abs(firstValue - list[i]);
            }

        }
        return minSub;
    }

    ///////////////////////// 배열 내에서 최소 차이값을 구하는 코드
    static int FindMinimumValue(List<int> list)
    {
        int minNum = FindDifferenceValue(list, 0);

        for (int i = 0; i < list.Count; i++)
        {
            if (FindDifferenceValue(list, i) < minNum)
            {
                minNum = FindDifferenceValue(list, i);
            }
        }

        return minNum;
    }

    //////////////////////// 스왑 함수
    static void Swap(List<int> list, int a, int b)
    {
        int tmp = list[a];
        list[a] = list[b];
        list[b] = tmp;
    }

    ////////////////////////  배열에서 최솟값 찾는 함수
    static int IndexOfMinimum(List<int> list, int startPoint)
    {
        int minNum = list[startPoint];
        int minIndex = startPoint;

        for (int i = startPoint + 1; i < list.Count; i++)
        {
            if (list[i] < minNum)
            {
                minNum = list[i];
                minIndex = i;
            }
        }
        return minIndex;
    }

    //////////////////////// 선택정렬 함수
    static void SelectionSort(List<int> list)
    {
        for (int i = 0; i < list.Count; i++)
        {
            var minIndex = IndexOfMinimum(list, i);
            Swap(list, i, minIndex);
        }
    }
}

 

우선 함수로 (1)선택정렬 함수를 만들고 수를 정렬시킵니다. 그 후 (2)배열의 특정인덱스를 다른 모든 수와 비교하여 최소차이값을 구하는 함수를 만들었습니다. 그리고 이 함수를 이용해서 (3)전체 배열 중 최소차이값을 구하는 함수를 만들었습니다. 이렇게 배열 내 최소의 차이값을 출력하는 프로그램을 만들었습니다.

 

첫 번째, 두 번째 테스트 케이스를 무난하게 통과했습니다. 

 

 

하지만 세 번째 경우는 통과하지 못했습니다. 역시나 선택정렬(O(n^2))을 쓴 결과 타임 초과가 나버리고 말았습니다. 그럼 위 코드에서 선택정렬 코드를 시간처리가 빠른 다른 정렬 코드로 바꿔줘야합니다. 이런게 가능한 정렬로는 대표적으로 퀵 정렬이 있습니다.

 

그럼 정렬 부분을 다르게해서 다시 풀어보겠습니다.

 

//19.10.02작성완료 이후 정렬에 대해 배우고나서 다시 작성예정