[프로그래머스] 8: 직사각형 별찍기, 최대공약수와 최대공배수, 3진법 뒤집기, 이상한 문자 만들기, 겹치는 선분의 길이

서예진·2024년 1월 18일
0

목차

▸ Lv.1
1. 직사각형 별찍기
2. 최대공약수와 최대공배수
3. 3진법 뒤집기
4. 이상한 문자 만들기
▸ Lv.0
5. 겹치는 선분의 길이


1. 직사각형 별찍기 : Lv.1

▼ 문제
이 문제에는 표준 입력으로 두 개의 정수 n과 m이 주어집니다.
별(*) 문자를 이용해 가로의 길이가 n, 세로의 길이가 m인 직사각형 형태를 출력해보세요.

▼ 제한 조건

  • n과 m은 각각 1000 이하인 자연수입니다.

▼ 예시

입력
5 3

출력
*****
*****
*****

▼ 내 풀이

import java.util.Scanner;

class Solution {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();
        
        for(int i = 0; i<b; i++){
            for(int j = 0; j<a; j++){
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
  • 반복적으로 *을 찍기 때문에 이중 for문을 사용한다.

2. 최대공약수와 최대공배수 : Lv.1

▼ 문제
두 수를 입력받아 두 수의 최대공약수와 최소공배수를 반환하는 함수, solution을 완성해 보세요. 배열의 맨 앞에 최대공약수, 그다음 최소공배수를 넣어 반환하면 됩니다. 예를 들어 두 수 3, 12의 최대공약수는 3, 최소공배수는 12이므로 solution(3, 12)는 [3, 12]를 반환해야 합니다.

▼ 제한 사항

  • 두 수는 1이상 1000000이하의 자연수입니다.

▼ 입출력 예

nmreturn
312[3, 12]
25[1, 10]

▼ 내 풀이

class Solution {
    public int[] solution(int n, int m) {
        int[] answer = new int[2];
        int maxnum = n;
        int gcd = 0;
        
        if(n<m){
            maxnum = m;
        }
        
        for(int i = 1; i<=maxnum; i++){
            if(n%i==0 && m%i==0){
                gcd = i;
            }
        }
        
        int lcm = (n*m)/gcd;
        answer[0] = gcd;
        answer[1] = lcm;
        return answer;
    }
}
  • if문을 활용하여 최대공약수를 구하고 두 수를 곱하고 최대공약수로 나누면 최소공배수가 되기 때문에 해당 연산을 코드로 만들었다.

3. 3진법 뒤집기 : Lv.1

▼ 문제
자연수 n이 매개변수로 주어집니다. n을 3진법 상에서 앞뒤로 뒤집은 후, 이를 다시 10진법으로 표현한 수를 return 하도록 solution 함수를 완성해주세요.

▼ 제한사항

  • n은 1 이상 100,000,000 이하인 자연수입니다.

▼ 입출력 예

nresult
457
125229

▼ 내 풀이

import java.util.List;
import java.util.ArrayList;

class Solution {
    public int solution(int n) {
        int answer = 0;
        List<Integer> remainder = new ArrayList<>();
        
        while(true){
            int share = n/3;
            remainder.add(n%3);
            n = share;
            if(share==0){
                break;
            }
        }
        int[] reverse = new int[remainder.size()];
        for(int i = 0; i<reverse.length; i++){
            reverse[i] = remainder.get(reverse.length-i-1);
        }
        for(int i = 0; i<reverse.length; i++){
            answer += reverse[i]*Math.pow(3,i);
        }
        return answer;
    }
}
  • 우선, 3진법을 먼저 표현해야겠다고 생각했기 때문에 몫이 0일때까지 3으로 나누는 것을 반복하고 나머지를 저장할 리스트를 만들었다.
  • 나머지를 저장할 리스트는 연산 순서대로 값이 들어가기 때문에 거꾸로 정렬을 해준다.
  • 완성된 나머지 값들이 들어있는 배열은 인덱스가 왼쪽부터 시작되기 때문에 문제에서처럼 3진법을 거꾸로 뒤집을 필요가 없다.
  • 그 다음 10진법으로 표현하는 연산을 for문을 활용하여 만들었다.

4. 이상한 문자 만들기 : Lv.1

▼ 문제
문자열 s는 한 개 이상의 단어로 구성되어 있습니다. 각 단어는 하나 이상의 공백문자로 구분되어 있습니다. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을 리턴하는 함수, solution을 완성하세요.

▼ 제한 사항

  • 문자열 전체의 짝/홀수 인덱스가 아니라, 단어(공백을 기준)별로 짝/홀수 인덱스를 판단해야합니다.
  • 첫 번째 글자는 0번째 인덱스로 보아 짝수번째 알파벳으로 처리해야 합니다.

▼ 입출력 예

sreturn
"try hello world""TrY HeLlO WoRlD"

▼ 내 풀이

[오답코드]
class Solution {
    public String solution(String s) {
        String answer = "";
        String[] array = s.split(" ");
        
        for(int i = 0; i<array.length; i++){
            String sko = array[i];
            char[] chararray = sko.toCharArray();
            for(int j = 0; j<chararray.length; j++){
                if(j%2==0){
                    if(Character.isLowerCase(chararray[j])){
                        chararray[j] = Character.toUpperCase(chararray[j]);
                    }
                } else{
                    if(Character.isUpperCase(chararray[j])){
                        chararray[j] = Character.toLowerCase(chararray[j]);
                    }
                }
            }
            array[i] = String.valueOf(chararray);
            answer = String.join(" ",array);
        }
        return answer;
    }
}
  • 우선 split 메소드를 활용하여 공백을 기준으로 문자열을 나누어야 겠다고 생각했다. -> ["try", "hello", "world"]
  • 이렇게 완성된 문자열 배열의 요소를 하나씩 가져와 char타입의 배열로 바꾸고 해당 배열의 인덱스에 접근할 수 있게 했다. -> ['t', 'r', 'y'] ,,,
  • 인덱스가 짝수일 때 소문자인 경우에만 대문자로, 홀수일 때 대문자인 경우에만 소문자로 바꾸게 했다.
  • 완성된 문자열 배열을 문자열로 합쳐줬다.
  • 해당 코드는 테스트 4,5,8,9,11에서 실패가 떴다.
  • 알아보니 내가 틀린 테스트와 같은 테스트들을 틀린 분이 계셨고 그 분은 split 부분에서 split(" ", -1)로 해결하셨다.
[수정코드]
class Solution {
    public String solution(String s) {
        String answer = "";
        String[] array = s.split(" ", -1);
        
        for(int i = 0; i<array.length; i++){
            String sko = array[i];
            char[] chararray = sko.toCharArray();
            for(int j = 0; j<chararray.length; j++){
                if(j % 2 == 0){
                    if(Character.isLowerCase(chararray[j])){
                        chararray[j] = Character.toUpperCase(chararray[j]);
                    }
                } else if(j % 2 == 1){
                    if(Character.isUpperCase(chararray[j])){
                        chararray[j] = Character.toLowerCase(chararray[j]);
                    }
                }
            }
            array[i] = String.valueOf(chararray);
        }
        answer = String.join(" ",array);
        return answer;
    }
}
  • split(" ")와 같이 사용되면 문자열 양 끝의 공백이나 여러 개의 연속된 공백이 있을 경우를 제대로 처리하지 못한다.
  • split(" ", -1)은 위에서 제대로 처리되지 못한 부분까지 제대로 처리해준다.
  • 문제를 다시보니 공백이 문자열 사이에 한 번만 나타난다는 전제도 없고 문자열 양 끝에 나타나지 않는다는 전제도 없었기 때문에 split(" ", -1)을 생각했어야 했다.

5. 겹치는 선분의 길이 : Lv.0

▼ 문제
선분 3개가 평행하게 놓여 있습니다. 세 선분의 시작과 끝 좌표가 [[start, end], [start, end], [start, end]] 형태로 들어있는 2차원 배열 lines가 매개변수로 주어질 때, 두 개 이상의 선분이 겹치는 부분의 길이를 return 하도록 solution 함수를 완성해보세요.

lines가 [[0, 2], [-3, -1], [-2, 1]]일 때 그림으로 나타내면 다음과 같습니다.

선분이 두 개 이상 겹친 곳은 [-2, -1], [0, 1]로 길이 2만큼 겹쳐있습니다.

▼ 제한 사항

  • lines의 길이 = 3
  • lines의 원소의 길이 = 2
  • 모든 선분은 길이가 1 이상입니다.
  • lines의 원소는 [a, b] 형태이며, a, b는 각각 선분의 양 끝점 입니다.
    • -100 ≤ a < b ≤ 100

▼ 입출력 예

linesresult
[[0, 1], [2, 5], [3, 9]]2
[[-1, 1], [1, 3], [3, 9]]0
[[0, 5], [3, 9], [1, 10]]8

▼ 내 풀이

  • 배열을 만들어서 겹치는 부분을 x로 표시하고 x의 수를 세는 방법은 어떨지 생각했다.
  • 해당 방법대로 코드를 짰지만 잘 돌아가지 않아 다른 방법을 찾았다.
  • x로 표시가 아니라 ++1하는 방법으로 접근하면 어떨까
[오답코드]
class Solution {
    public int solution(int[][] lines) {
        int answer = 0;
        int min = lines[0][0];
        int max = lines[0][0];
        for(int i = 0; i < lines.length; i++){
            for(int j = 0; j < lines[0].length; j++){
                if(min > lines[i][j]){
                    min = lines[i][j];
                }
                if(max < lines[i][j]){
                    max = lines[i][j];
                }
            }
        }
        int length = max - min;
        
        int[] line = new int[length];
        
        if(min<0){
            int d = 0 - min;
            for(int i = 0; i<lines.length; i++){
                for(int j = 0; j<lines[0].length; j++){
                    lines[i][j] = lines[i][j]+d;
                }
            }
        }✔️
        
        for(int i =0; i<lines.length; i++){
            for(int j = lines[i][0]; j<lines[j][1]📍; j++){
                line[j] += 1;
            }
        }
        for(int i : line){
            if(i>1){
                answer += 1;
            }
        }
        return answer;
    }
}
  • 이렇게 작성했지만 계속해서 인덱스를 벗어나는 오류가 떴고 찾아보니 알고보니 📍-> 이 부분을 잘못 작성했다.
  • 또한, ✔️ -> 이 부분은 불필요한 부분이므로 다음과 같이 수정했다.
[수정코드]
class Solution {
    public int solution(int[][] lines) {
        int answer = 0;
        int min = lines[0][0];
        int max = lines[0][0];
        for(int i = 0; i < lines.length; i++){
            for(int j = 0; j < lines[0].length; j++){
                if(min > lines[i][j]){
                    min = lines[i][j];
                }
                if(max < lines[i][j]){
                    max = lines[i][j];
                }
            }
        }
        int length = max - min;
        int d = 0 - min;
        int[] line = new int[length];
        for(int i =0; i<lines.length; i++){
            for(int j = lines[i][0]+d; j<lines[i][1]+d; j++){
                line[j] += 1;
            }
        }
        for(int i : line){
            if(i>1){
                answer += 1;
            }
        }
        return answer;
    }
}
profile
안녕하세요

0개의 댓글