TIL_250409

듀듀·2025년 4월 9일

spring_TIL

목록 보기
38/53

삼각 달팽이

링크텍스트

문제 설명

  1. 길이와 높이가 n인 삼각형에 반시계 방향으로 숫자를 1씩 늘려서 넣는다.
  2. 배열로 반환

시행 착오 및 문제 풀이

우선 오답 풀이 먼저....

오답 풀이

  1. 우선 아래로 내려가는 것은 n번 반복, 오른쪽으로 가는 것은 n-1번 반복, 왼쪽 대각선으로 올라가는 것은 n-2번 반복 -> 계속 반복하여 삼각형을 만든다. 그러므로 n이 0이 되기 전까지 반복한다.
  2. count 변수를 만들어 이동하는 동안의 횟수를 구한다. 그것이 n보다 작을동안 반복해준다.
    2-1. 하나의 이동이 끝나면 count를 초기화하고 n-- 해준다.
  3. 아래로 내려가는 것은 i++, 오른쪽으로 가는 것은 j++, 왼쪽 대각선은 i-- j--
  4. 삼각형 안에 들어있는 수를 answer에 담아준다. 0인 경우가 들어가면 안되므로 0이 아닐 때의 조건을 추가해서 반환해준다.

오답 코드

import java.util.*;
class Solution {
    public int[] solution(int n) {
        int[] answer = new int[(n*(n+1))/2];
        int[][] arr = new int[n+1][n+1];
        int i = 0;
        int j = 0;
        int count = 0;
        int num = 1;

        while(n>0) {
            //밑으로 내려가기
            while(count<n) {
                arr[i][j] = num++;
                i++;
                count++;
            }
            count = 0;
            n--;
            
            //오른쪽으로 가기
            while(count<n) {
                arr[i][j] = num++;
                j++;
                count++;
            }
            count = 0;
            n--;
            
            //왼쪽 대각선
            while(count<n) {
                arr[i][j] = num++;
                i--;
                j--;
                count++;
            }
            count = 0;
            n--;
            
        }
        
        int idx = 0;
        for(int k=0; k<arr.length; k++) {
            for(int h=0; h<arr[0].length; h++) {
                if(arr[k][h] != 0) {
                    answer[idx] = arr[k][h];
                    idx++;
                }
                
            }
        }
            
        return answer;
    }
}

결과

테스트 1
입력값 〉	4
기댓값 〉	[1, 2, 9, 3, 10, 8, 4, 5, 6, 7]
실행 결과 〉	실행한 결괏값 [1,2,3,10,4,9,5,6,7,8]이 기댓값 [1,2,9,3,10,8,4,5,6,7]과 다릅니다.
테스트 2
입력값 〉	5
기댓값 〉	[1, 2, 12, 3, 13, 11, 4, 14, 15, 10, 5, 6, 7, 8, 9]
실행 결과 〉	실행한 결괏값 [1,2,3,13,4,14,12,5,15,11,6,7,8,9,10]이 기댓값 [1,2,12,3,13,11,4,14,15,10,5,6,7,8,9]과 다릅니다.
테스트 3
입력값 〉	6
기댓값 〉	[1, 2, 15, 3, 16, 14, 4, 17, 21, 13, 5, 18, 19, 20, 12, 6, 7, 8, 9, 10, 11]
실행 결과 〉	실행한 결괏값 [1,2,3,16,4,17,15,5,18,14,6,19,20,21,13,7,8,9,10,11,12]이 기댓값 [1,2,15,3,16,14,4,17,21,13,5,18,19,20,12,6,7,8,9,10,11]과 다릅니다.
테스트 결과 (~˘▾˘)~
3개 중 0개 성공

뭐야? 순간 맞은 줄;
또 연습장에 내 코드대로 촵촵 풀어봤더니.. 문제 발견!
위 코드의 문제점은 i와 j가 제대로 갱신되지 않아서 생긴것이었다!

즉, 첫 사이클 끝난 후 i = 1, j = 1인데, 바로 그 다음에 i++하면 위치가 틀어진다. 이런 식으로 방향 전환 후 다음 시작점 위치가 꼬이고, 결과 순서가 망가져버리는 이슈..


정답 풀이

i와 j는 다음 반복에서 영향을 주기 때문에 마지막 arr에 들어간 i, j값이 고대로 다음 반복으로 넘어가야 한다. 하지만 내 코드는 arr에 넣은 후 i와 j의 값이 변경된다. 이 부분을 수정했다.

정답 코드

import java.util.*;
class Solution {
    public int[] solution(int n) {
        int[] answer = new int[(n*(n+1))/2];
        int[][] arr = new int[n+1][n+1];
        int i = -1;
        int j = 0;
        int count = 0;
        int num = 1;

        while(n>0) {
            //밑으로 내려가기
            while(count<n) {
                i++;
                arr[i][j] = num++;
                count++;
            }
            count = 0;
            n--;
            
            //오른쪽으로 가기
            while(count<n) {
                j++;
                arr[i][j] = num++;
                count++;
            }
            count = 0;
            n--;
            
            //왼쪽 대각선
            while(count<n) {
                i--;
                j--;
                arr[i][j] = num++;
                count++;
            }
            count = 0;
            n--;
            
        }
        
        int idx = 0;
        for(int k=0; k<arr.length; k++) {
            for(int h=0; h<arr[0].length; h++) {
                if(arr[k][h] != 0) {
                    answer[idx] = arr[k][h];
                    idx++;
                }
                
            }
        }
            
        return answer;
    }
}

x=-1.. 약간 임시방편? 느낌으로 했는데 맞아서 당황했다;
당연히 x=0, y=0으로 두고 후위증가를 했더니 틀리길래 연습장에 슥슥 풀어본 결과 먼저 x와 y를 증가하거나 감소한 뒤 arr에 넣어야 맞는 답이 나오더라. 그러기 위해서는 x가 -1부터 시작해야 하는데... 싶어서 -1로 바꿔서 돌려봤는데 정답이였다..

암튼 이렇게 정답! ㅎㅎ

다른 정답 코드

import java.util.*;
class Solution {
    public int[] solution(int n) {

        int[][] arr = new int[n][n];
        
        int x = -1;
        int y = 0;
        
        int num = 1;
        
        for(int i=0; i<n; i++) {
            //아래
            if(i%3==0) {
                for(int j=i; j<n; j++) {
                    x++;
                    arr[x][y] = num++;
                }
            }
            
            //오른쪽
            else if(i%3==1) {
                for(int j=i; j<n; j++) {
                    y++;
                    arr[x][y] = num++;
                }
            }
            
            //왼쪽 대각선
            else if(i%3==2) {
                for(int j=i; j<n; j++) {
                    x--;
                    y--;
                    arr[x][y] = num++;
                }
            }
        }
            
        //answer에 넣기
        int[] answer = new int[(n*(n+1))/2];
        int idx = 0;
        
        for(int i=0; i<n; i++) {
            for(int j=0; j<n; j++) {
                //0이 아닐경우
                if(arr[i][j] != 0) {
                    answer[idx] = arr[i][j];
                    idx++;
                }
            }
        }
        return answer;
    }
}
  1. 삼각형이므로 3번씩 끊어서 반복. 그러므로 번호표(쉽게 생각하고 싶어서...)라고 생각하고 나머지(%3)를 통해서 아래, 오른쪽, 왼쪽대각선을 나눠서 반복하였다. 그걸 n번 반복하였다.
  2. 오답풀이에서 한 n-1번 반복을 j=i를 n까지 반복하는 방식으로 변경했다. n을 계속 줄이는 것보다 위험 부담이 줄어들지 않았을까..?^^
  3. x=-1로 두고 먼저 증가한 다음 arr에 넣어줬다. 안그러면 오답 풀이때처럼 x가 틀리기 때문에~
  4. 나머지는 위의 방식과 동일하게

예전 풀이를 보니 이중 for문을 통해 풀었더라
고거 참고해서 한번 더 풀어봄
내가 푼 코드보다 훨씬 깔끔해 보이는 건 기분탓일까...?


이 문제도 즐찾 되어있어서 일단 쫄고 시작했고... 역시나 쉽지 않더라
아 푸는 방법은 알겠는데 뭔가 코드로 만드는게 쉽지 않다.
이전에 풀었던 방식이랑 현재 푼 방식이 다른 것도 신기하다
같은 문제, 같은 머리인데도 다른 풀이가 나와버리고~
시야가 넓어진거라고 생각할게요 &*

0개의 댓글