C# : 배열과 리스트의

rain cloud·2025년 7월 15일
0

TIL

목록 보기
4/11
post-thumbnail

📕 정리 중점

  • 오늘 풀은 문제들을 중심으로 배열과 리스트의 활용에 있어서 혼란이 와서 이런 것들을 중심으로 배열의 문법과 리스트의 사용을 비교해서 정리를 할 생각이다.

1번 프로그래머스 : 카운트 다운

  • 문제 : 정수 start_num와 end_num가 주어질 때 start_num에서 end_num까지 1씩 감소하는 수들을 차례로 담은 리스트를 return하도록 solution 함수를 완성해주세요.

  • 해결 시도 :

    using System;
    
    public class Solution {
    	public int[] solution(int start_num, int end_num) {
    
    	int[] answer = new int[] {};
    	for (int i = start_num; i >=end_num; i--)
    	{
    	answer[i] += start_num;
    	Console.WriteLine(string.Join(", ",answer[i]));
    	}
    }
    }
    • 처음에는 이렇게 작성을 했다.
    • 배열의 출력이니까 당연히 for문을 비롯한 반복문의 사용은 필수 였고, start_num과 end_num이라는 정확한 범위가 있으므로 for문을 사용하고자 하였다.
    • 그리고 1씩 감소한다고 했으니까 i의 시작점을 start_num, 마지막 지점을 end_num으로 설정하고 i--로 1씩 감소하게 하고자 하였다.
    • 이렇게 설계를 하고 위의 코드를 작성하였으나 코드가 제대로 작동하지 않았다.
      => 이유는 배열의 문법을 제대로 지키지 않았기 때문이었다.
  • 해결 :

    using System;
    
    public class Solution {
        public int[] solution(int start_num, int end_num) {
            int[] answer = new int[start_num - end_num +1];
    
            for (int i = start_num; i >= end_num; i--)
            {
                answer[start_num - i] = i;
            }
    
            Console.WriteLine("[" + string.Join(", ", answer)+"]");
    
            return answer;
        }
    }
    • 해결 시도에서 작성했던 코드와 비교해서 보자면, 일단 int[] answer = new int[]{}; 이런 식으로 선언을 할 수가 없다.
    • 배열을 빈 배열로 선언하면 IndexOutOfRangeException이 발생하게 된다.
    • 그 이유는 배열은 리스트와 달리 배열을 생성할 때 heap 메모리 영역에 얼만큼의 공간이 필요한지를 정확히 전해줘야 하기 때문이다.
    • 예를 들어 int[] answer = new int[5];라고 했다면, 이 배열을 생성하기 위해 heap의 메모리 영역에 딱 5칸의 영역을 비우고, 그곳에 answer 배열을 저장하게 된다.
    • 이 영역을 넘으려고 하면 이미 6번째 칸에는 다른 heap 메모리가 있기때문에 확장이 안되는 것.
    • 그런데 아예 그런 영역을 작성하지 않았기 때문에 애초에 생성이 안되는 것이다.
    • 그래서 정확한 배열의 크기를 지정해 주기 위해 start_num - end_num +1 을 해주었다.
    • +1은 인덱스라서 더해줬다.
    • 아 그리고 +=으로 배열에 값 추가하는 건 없는 방식이라서 그냥 =으로 해주면 된다.
    • 보통 프로그래머스 같은 경우는 자동으로 return answer만 해도 배열값이 출력되는 경우가 있는데, 이 그보다는 내부적으로 foreach문을 사용하여 출력하는 string.Join을 써서 ',' 구분자로 배열을 출력하게 해주었다.

2. 프로그래머스 : 리스트 자르기

  • 문제는 정수 n과 정수 3개가 담긴 리스트 slicer 그리고 정수 여러개가 담긴 리스트 num_list가 주어진다. slicer에 담긴 정수를 차례대로 a,b,c라고 할 때, n에 따라 num_list를 슬라이싱 하려고 한다.

  • 세부 조건이 3가지 있는데 각각 n의 값에 따라 num_list의 출력 인덱스 범위를 지정하는 것이었다. (프로그래머스 기초 트레이닝에서 찾아볼 수 있다)

  • 해결 시도

    public int[] solution(int n, int[] slicer, int[] num_list)
    {
    int[] answer = new int[];
    
    while (true)
    {
    	if (n == 1)
    	{
    		for (int i = 0; i <= slicer[1]; i++)
    			answer = num_list[i];
    			break;
    	}
    	else if (n == 2)
    	{
    		for (int i = slicer[0]; i < num_list.Length(); i++)
    			answer = num_list[i];
    			break;
    	}
    	else if (n == 3)
    	{
    		for (int i = slicer[0]; i <= slicer[1]; i++)
    		{
    			answer = num_list[i];
    		}
    		break;
    	}
    	else if (n == 4)
    	{
    		for (int i = slicer[0]; i <= slicer[1]; i += slicer[2])
    			answer = num_list[i];
    		 	break;
    	}
    
    }
    }
    • 문제는 n의 값이 1~4일 때 각 num_list의 출력값을 나누도록 하였다.

    • 일단 초기값으로 int[] answer = new int[];가 선언되어 있었기 때문에 그대로 사용하고자 했고, n의 값에 따라 범위가 바뀌므로 if 문을 사용하고자 했다.

    • 그리고 배열을 출력해야 하니 for문을 통해서 조건에 맞게 범위를 지정하고자 하였다.

    • 아직도 의문인건 while을 왜 사용했었는지 나 스스로도 모르겠다. 아마 for문으로의 반복을 사용해 놓고 착각해서 추가해버린 것 같다.

    • 당연히 이렇게 작성했을 때 에러가 발생했다. 앞서 말했듯 int 배열의 크기를 명확히 지정하지 않았다.

    • 그리고 배열에 값을 대입하는 방식이 잘못되었는데, num_list[i]는 int[] 가 아니고, int 타입이기 때문에 int[] 배열인 answer에 대입을 하려고 하면 type mismatch가 발생하게 된다.

    • 이것을 해결하려면 배열이 아니라 List를 사용해서 .Add로 직접 추가해주는 방법과, 아니면 answer에 저장하는게 아니라 answer[i] = num_list[i]로 둘 다 type을 int로 맞춰주는 방식이 있다.

    • 아 그리고 Length는 그냥 속성이라 괄호 빼야 한다.

  • 해결

    using System;
    using System.Collections.Generic;
    
    public class Solution {
        public int[] solution(int n, int[] slicer, int[] num_list)
        {
            List<int> answer = new List<int>();
    
            if (n == 1)
            {
                for (int i = 0; i <= slicer[1]; i++)
                {
                    answer.Add(num_list[i]);
                }
            }
            else if (n == 2)
            {
                for (int i = slicer[0]; i < num_list.Length; i++)
                {
                    answer.Add(num_list[i]);
                }
            }
            else if (n == 3)
            {
                for (int i = slicer[0]; i <= slicer[1]; i++)
                {
                    answer.Add(num_list[i]);
                }
            }
            else if (n == 4)
            {
                for (int i = slicer[0]; i <= slicer[1]; i += slicer[2])
                {
                    answer.Add(num_list[i]);
                }
            }
    
            return answer.ToArray();
        }
    }
    
    • 사실 slicer 정수 배열의 요소들에 맞춰서 크기가 계속 변하기 때문에 가변적이라고 할 수 있다.
    • 따라서 배열을 써서 추가적인 요소를 사용하기보다는 List를 사용하여 가변적인 크기 변화에 대처하는 것이 좋다고 판단 했다.
    • answer를 리스트로 선언하고 만들어 줬다.
    • 의미없는 while 반복문을 제거 했고, answer.Add(num_listp[i]);로 answer리스트에 num_list의 요소들을 넣어주었다.
    • 마지막에 return answer.ToArray()는 solution 메서드의 반환타입이 int[]로 배열이라서, ToArray()로 리스트를 다시 배열로 변환하여 반환하게 하였다.

문제를 통해 알게된 문법 정리

  • 배열은 선언할 때 크기를 결정해야 하고, 또 그 크기를 변경할 수 없다.

    int[] arr = new int[3]; // 크기 고정
    arr[0] = 10;            // 값 할당만 가능
    
  • 리스트는 선언 후 크기를 자유롭게 조정할 수 있다.

    List<int> list = new List<int>();
    list.Add(10);           // 크기 자유롭게 추가 가능
    list.Add(20);
    
  • 배열, 리스트 둘 다 값에는 인덱스로 접근한다.

    arr[0] = 5;
    list[0] = 5;
    
  • 배열=> 리스트, 리스트<=배열의 형변환이 가능하다.

List<int> list2 = arr.ToList(); //배열 =>리스트
int[] arr2 = list.ToArray();  // 리스트 => 배열
  • 또 불필요한 반복문 없이 그냥 한 줄로만 배열, 리스트를 출력할 수 있는 방법이 있다.

    Console.WriteLine(string.Join(", ", arr));
    Console.WriteLine(string.Join(", ", list));
    
    • string.Join은 내부적으로 foreach문을 사용한다.

    => 배열/리스트 관련 코딩을 할 때에믄 크기가 고정인지 추가, 삭제가 많은 작업인지, 혹은 반환형이 어떻게 되는지를 살펴본다면 배열과 리스트 중 어떤걸 써야 하는지 쉽게 판단할 수 있다.


profile
게임 개발, 기획

0개의 댓글