프로그래머스 - C#

3. 프로그래머스 - 연속된 부분 수열의 합

seqw 2023. 5. 31. 14:24

 

 문제 설명

 비내림차순으로 정렬된 수열이 주어질 때, 다음 조건을 만족하는 부분 수열을 찾으려고 합니다.


  - 기존 수열에서 임의의 두 인덱스의 원소와 그 사이의 원소를 모두 포함하는 부분 수열이어야 합니다.
  - 부분 수열의 합은 k입니다.
  - 합이 k인 부분 수열이 여러 개인 경우 길이가 짧은 수열을 찾습니다.
  - 길이가 짧은 수열이 여러 개인 경우 앞쪽(시작 인덱스가 작은)에 나오는 수열을 찾습니다.

 수열을 나타내는 정수 배열 sequence와 부분 수열의 합을 나타내는 정수 k가 매개변수로 주어질 때, 위 조건을 만족하는 부분  수열의 시작 인덱스와 마지막 인덱스를 배열에 담아 return 하는 solution 함수를 완성해주세요.
 이때 수열의 인덱스는 0부터 시작합니다.

 

 문제 해결



 1. 주어지는 건 1차원 배열이지만 s ~ e 까지의 합이라는 조건 때문에 2차원 배열처럼 사용할 수 있다.
    이를 통해 조건을 맞추면 맵에서 이동하듯 0,0 부터 4,4 까지 원하는 수를 밟아가며 이동할 수 있게 된다.

 2. Start와 End는 0부터 시작

 3. 현재 수가 원하는 수보다 작거나 같다면 End를 증가

 4. 현재 수가 원하는 수보다 크다면 Start를 증가

 5. Start는 End보다 커질 수 없음

 6. 원하는 수를 찾았다면 Start를 증가시킴

 7. 만약 End가 끝에 도달했다면 Start를 증가시킴

 8. 정답을 고를때 밟은 곳의 Start와 End거리가 가장 가까운것을 우선적으로 선택함

 

    public class Node
    {
        public Node(int s, int e)
        {
            str = s;
            end = e;
            len = e - s;
        }

        public int len;
        public int str;
        public int end;
    }

    public int[] solution(int[] sequence, int k)
    {
        int start = 0;
        int end = 0;
        int sum = sequence[0];

        List<Node> nodes = new List<Node>(sequence.Length);

        if (sum == k)
        {
            return new int[] { start, end };
        }
        
        int limit = sequence.Length - 1;
        while (true)
        {
            //값이 작거나 같고 끝에 닿지 않았을때
            if (sum <= k && end < limit)
            {
                sum += sequence[++end];
            }
            //값이 크거나 end가 끝에 도달했다면
            else if(sum > k || end == limit)
            {
                sum -= sequence[start++];
            }
            
            if (sum == k)
            {
                Node n = new Node(start, end);
                if (n.len == 0)
                {
                    return new int[] { start, end };
                }

                nodes.Add(new Node(start, end));
            }

            //둘다 끝에 도달했다면
            if (end == limit && start == limit)
            {
                break;
            }
        }

        nodes.Sort((item1, item2) => item1.len.CompareTo(item2.len));

        return new int[] { nodes[0].str, nodes[0].end };
    }

 

어떻게 해야할지 해매다가 일단 공책에 표를 만들어보니 맵처럼 이동이 가능하겠다는 생각이 들어서 해결한 문제

문제를 풀고나서 다른 사람의 풀이를 보니 내가 사용한 방법이 투 포인터라는 이름으로 이미 있었다.