티스토리 뷰

1️⃣ 문자열 다루기 기본

 

문제 설명

문자열 s의 길이가 4 혹은 6이고, 숫자로만 구성돼있는지 확인해주는 함수, solution을 완성하세요. 예를 들어 s가 "a234"이면 False를 리턴하고 "1234"라면 True를 리턴하면 됩니다.

제한사항

  • s는 길이 1 이상, 길이 8 이하인 문자열입니다.
  • s는 영문 알파벳 대소문자 또는 0부터 9까지 숫자로 이루어져 있습니다.

 

입출력 예

s return
"a234" false
"1234" true

 

 

💻 나의 풀이

class Solution {
    public boolean solution(String s) {
        if(s.length() == 4 || s.length() == 6) {    // 길이가 4 혹은 6 인지
        	for(int i=0; i<s.length(); i++) {
            		if(s.charAt(i) < '0' || s.charAt(i) > '9') {
               		 return false;
                }
            }
        	return true;    
        } else return false;
    }
}

 

for문과 if문을 사용한 첫 번째 풀이 입니다. 

length()메소드로 문자열의 길이를 판별하고, charAt() 메소드로 문자가 숫자가 아닌지 확인합니다.

그런데 별로 좋은 풀이 같지 않습니다.

 

 

🔍 다른 사람의 풀이

class Solution {
    public boolean solution(String s) {
        if (s.length() == 4 || s.length() == 6) {
            return s.matches("(^[0-9]*$)");
        }
        
        return false;
    }
}

 

정규표현식을 사용한 풀이입니다. 훨씬 깔끔합니다.

0단계에서 정규표현식을 사용한 적이 있어 떠오르긴 했었는데 matches() 메소드를 몰라서 활용을 못했네요. ㅠㅠ

 

^[0-9]*$는 정규표현식으로, 문자열이 0부터 9까지의 숫자로만 이루어져 있는지 확인하는 패턴입니다. 

  • ^: 문자열의 시작을 나타냅니다.
  • [0-9]: 0부터 9까지의 숫자 중 하나와 일치합니다.
  • *: 0 또는 그 이상의 문자와 일치합니다.
  • $: 문자열의 끝을 나타냅니다.
💡 s.matches
메서드는 정규표현식을 사용하여 문자열이 패턴과 일치하는지를 확인합니다. 

 

💡 정규표현식
문자열의 패턴을 정의하기 위한 표현식입니다.
Java에서는 matches 메서드를 통해 정규표현식을 활용하여 문자열 패턴을 확인할 수 있습니다.

✔ 숫자 여부 확인
\\d는 모든 숫자를 의미합니다.
+는 하나 이상의 문자와 일치함을 나타냅니다.
s.matches("\\d+"); // 문자열이 모두 숫자로 이루어져 있는지 확인​



알파벳 여부 확인
\\w는 모든 단어 문자(알파벳 대소문자, 숫자, 언더스코어)를 의미합니다.

+는 하나 이상의 문자와 일치함을 나타냅니다.

s.matches("\\w+"); // 문자열이 알파벳과 숫자로 이루어져 있는지 확인

 


✔ 길이 확인
{n}은 n번 반복을 나타냅니다.
{n, m}은 n부터 m까지의 반복을 나타냅니다.
s.matches(".{4}");    // 문자열이 4글자인지 확인
s.matches(".{4,6}");  // 문자열이 4글자에서 6글자 사이인지 확인​


✔ 특정 문자 포함 여부 확인
.*  는 모든 문자와 일치하는 패턴입니다.
s.matches(".*a.*");  // 문자열에 'a'가 포함되어 있는지 확인​


 

 


 

2️⃣ 행렬의 덧셈

 

문제 설명

행렬의 덧셈은 행과 열의 크기가 같은 두 행렬의 같은 행, 같은 열의 값을 서로 더한 결과가 됩니다. 2개의 행렬 arr1과 arr2를 입력받아, 행렬 덧셈의 결과를 반환하는 함수, solution을 완성해주세요.

제한사항

  • 행렬 arr1, arr2의 행과 열의 길이는 500을 넘지 않습니다.

 

입출력 예

arr1 arr2 return
[[1,2],[2,3]] [[3,4],[5,6]] [[4,6],[7,9]]
[[1],[2]] [[3],[4]] [[4],[6]]

 

 

💻 나의 풀이

class Solution {
    public int[][] solution(int[][] arr1, int[][] arr2) {
        int[][] answer = new int[arr1.length][arr2.length];    // 배열 answer 크기 초기화
        
        for(int i=0; i<arr1.length; i++) {    // 행렬의 행
            for(int j=0; j<arr1[i].length; j++) {    // 행렬의 열
                answer[i][j] = arr1[i][j] + arr2[i][j];
            }
        }
        
        return answer;
    }
}

 

먼저 배열 answer의 크기를 arr1배열과 arr2 배의 길이로 선언해줍니다.

그리고 첫 번째 for문으로 행렬의 행 만큼 반복하고, 두 번째 for문을 행렬의 열 만큼 반복합니다.

arr1과 arr2의 각각 같은 자리의 인덱스 값을 더 해서 answer행렬의 인덱스에 넣어줍니다.

 

 

그런데 테스트 2에서 실패했습니다.

0인 경우를 그대로 출력해서 그런것 같습니다.

 

class Solution {
    public int[][] solution(int[][] arr1, int[][] arr2) {
        int[][] answer = new int[arr1.length][arr1[0].length];
        
        for (int i = 0; i < arr1.length; i++) {   // 행의 길이
            for (int j = 0; j < arr1[i].length; j++) {    // 열의 길이 
                answer[i][j] = arr1[i][j] + arr2[i][j];
            }
        }
        
        return answer;
    }
}

 

성공한 두 번째 코드 입니다.

arr2.length를 arr1[0].length 으로 바꿔주었습니다.

각 행은 동일한 열의 개수를 가지기 때문에 열의 길이도 arr1의 행의 길이와 같습니다.

 

 

 

🔍 다른 사람의 풀이

class Solution {
    public int[][] solution(int[][] arr1, int[][] arr2) {
        int[][] answer = {};
        answer = arr1;
        for(int i=0; i<arr1.length; i++){
            for(int j=0; j<arr1[0].length; j++){
                answer[i][j] += arr2[i][j];
            }
        }
        return answer;
    }
}

 

어차피 배열 크기가 똑같으니까 answer을 그냥 arr1로 설정해도 됩니다.

 

 


 

3️⃣ 직사각형 별찍기

 

문제 설명

이 문제에는 표준 입력으로 두 개의 정수 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();           
        } 
    }
}

 

처음에 쓰여져 있는 기본 코드 때문에 더 헷갈릴 때가 있습니다;;

문제에는 n, m이라고 적혀있는데 코드에는 a, b로 되어있어 a, b로 진행했습니다.

안쪽 반복문은 열을 나타내고 주어진 a만큼 * 을 찍게 됩니다. 다 찍게 되면 안쪽 반복문을 벗어나고 바깥쪽 반복문이 실행됩니다.

바깥쪽 반복문은 행만큼 반복하게 되고, 한 행이 끝날 때마다 println으로 다음 행으로 넘어갑니다.

 

완전 처음 ( C언어 찍먹 시절 ) 에는 별 찍기 문제 가지고 몇날며칠을 이해하느라고 끙끙댔는데 이제는 별찍기가 제일 쉽네요ㅎㅎ 묘한 기분

 

 


 

 

4️⃣ 최대공약수와 최소공배수

 

문제 설명

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

제한사항

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

 

입출력 예

n m answer
3 12 [3,12]
2 5 [1,10]

 

 

💻 나의 풀이

class Solution {
    public int[] solution(int n, int m) {
        int[] answer = new int[2];  // 배열 크기를 2로 지정
        
        // 최대공약수
        int a = n, b = m;
        while(b != 0) {
            int r = a % b;
            a = b;
            b = r;
        } 
        answer[0] = a;  // 최대공약수 저장

        // 최소공배수
        answer[1] = (n * m) / a;  // 최소공배수 계산하여 저장
        
        return answer;
    }
}

 

최대공약수 최소공배수는 0단계에서 풀었던 기억이 있어 도움을 받으면서 풀었습니다.

=> 유클리드 호제법

 

하지만 첫 번째 코드는 테스트2에서 실패했는데요.

그 이유를 살펴보자면, 

마지막에 최소공배수를 계산할 때 answer[1] = (n * m) / a; 부분에서 실수가 있습니다. 최소공배수(LCM)는 두 수의 곱을 최대공약수(GCD)로 나눈 값입니다. 따라서 올바른 코드는 answer[1] = (n * m) / answer[0];로 수정되어야 합니다.

 

class Solution {
    public int[] solution(int n, int m) {
        int[] answer = new int[2];   // 배열 크기는 2
        
        // 최대공약수
        int a = n, b = m;
        while(b != 0) {
            int r = a % b;
            a = b;
            b = r;
        } 
        answer[0] = a;    
        
        // 최소공배수
        answer[1] = (n * m) / answer[0];
        
        return answer;
    }
}

 

수정해서 성공한 두 번째 코드 입니다.

유클리드 호제법과 최소공배수 구하는 방법부터 다시 기록해보자면 아래와 같습니다.

⭐ 유클리드 호제법 (최대공약수 구하기)
두 수 a, b의 최대공약수(GCD)는 bdhk a%b의 최대공약수(GCD)와 같다.
public static int gcd(int a, int b) {
    while (b != 0) {
        int r = a % b;
        a = b;
        b = r;
    }
    return a;
}​

 

⭐ 최소 공배수 (LCM) 구하기
두 수의 최대 공약수를 먼저 구한 후, 두 수의 곱셈을 최대 공약수로 나누어준다.
public int lcm(int a, int b) {
    int gcd = gcd(a, b);
    return (a * b) / gcd;
}

 

 

 

 

🔍 다른 사람의 풀이

class Solution {
    public boolean solution(int x) {
        int sum = 0;
        int n = x;
        
        while (n != 0) {
            sum += n % 10;   // 각 자릿수 구해서 sum 에 더하기
            n /= 10;   // 다음 자릿수로 넘어가기
        }
        
        return x % sum == 0? true : false;
    }
}

 

 

 


 

 

5️⃣ 같은 숫자는 싫어

 

문제 설명

배열 arr가 주어집니다. 배열 arr의 각 원소는 숫자 0부터 9까지로 이루어져 있습니다. 이때, 배열 arr에서 연속적으로 나타나는 숫자는 하나만 남기고 전부 제거하려고 합니다. 단, 제거된 후 남은 수들을 반환할 때는 배열 arr의 원소들의 순서를 유지해야 합니다. 예를 들면,

  • arr = [1, 1, 3, 3, 0, 1, 1] 이면 [1, 3, 0, 1] 을 return 합니다.
  • arr = [4, 4, 4, 3, 3] 이면 [4, 3] 을 return 합니다.

배열 arr에서 연속적으로 나타나는 숫자는 제거하고 남은 수들을 return 하는 solution 함수를 완성해 주세요.

제한사항

  • 배열 arr의 크기 : 1,000,000 이하의 자연수
  • 배열 arr의 원소의 크기 : 0보다 크거나 같고 9보다 작거나 같은 정수

 

입출력 예

arr answer
[1,1,3,3,0,1,1] [1,3,0,1]
[4,4,4,3,3] [4,3]

 

 

❌틀린코드

import java.util.*;

public class Solution {
    public int[] solution(int[] arr) {
        // 배열을 문자열로 변환
        String arrString = Arrays.toString(arr);
        
        // 문자열에서 숫자만 추출하여 배열로 변환
        String[] arrStrings = arrString.replaceAll("[^0-9]", "").split("");
        
        // 중복 제거 및 순서 유지
        Set<String> set = new LinkedHashSet<>(Arrays.asList(arrStrings));
        
        // Set을 정수 배열로 변환
        int[] answer = set.stream().mapToInt(Integer::parseInt).toArray();
        
        return answer;
    }
}

 

0단계 day13에서 풀었던 비슷한 문제가 떠올라서 똑같이 LinkedHashSet 으로 시도했던 코드.

테스트2에서는 통과지만 1에서는 실패다.

그 이유는?

만일 숫자가 [1,1,3,3,0,1,1]과 같이 주어졌을 때, 답이 [1,3,0] 이였다면 LinkedHashSet이 좋은 선택지였지만 이 문제는 아니였다.

 LinkedHashSet은 데이터의 중복을 허락하지 않음은 물론 입력 순대로 데이터를 관리한다.

 

 

💻 나의 풀이

import java.util.*;

public class Solution {
    public int[] solution(int[] arr) {
        int[] answer;
        
        // integer를 담는 stack 선언
        Stack<Integer> st = new Stack<Integer>();
        
        // 전달 받은 배열만큼 반복
        for(int i=0; i<arr.length; i++) {
            // 배열의 첫 번째 요소를 stack에 삽입
            if(i==0) st.push(arr[i]);           
            // 인덱스 1부터는 stack의 최상단 값(peek)이 arr[i]의 값과 일치 여부 확인 후,
            // 일치하지 않을 경우에만 stack에 push함
            else if(st.peek() != arr[i]) st.push(arr[i]);
        }
        
        answer = new int[st.size()];   // answer의 크기는 stack의 사이즈와 동일하게 생성
        
        // stack의 사이즈만큼 순회하면서
        // stack에서 꺼낸 값들을 pop하여 담을건데
        // stack은 LIFO => 실제 배열의 역순이므로
        // 역순으로 담아야 순서대로 담기게 된다. => i가 st.size()-1부터, -1씩 줄이면서, 0보다 클 때까지 반복
        for(int i=st.size()-1; i>=0; i--) {
            answer[i] = st.pop();
        }

        return answer;
    }
}

 

stack을 이용했습니다.

stack은 이론으로만 보고 써먹어본 적이 없는데 이번 문제를 계기로 확실하게 이해되었습니다.

 

먼저 아래 링크에서 stack 개념을 다시 한 번 정리할 수 있었습니다.

https://velog.io/@alkwen0996/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%8A%A4%ED%83%9DStack

 

코드 풀이

1. integer형 stack을 선언

2. 전달 받은 배열 arr 만큼 반복하면서 첫번째 값 arr[0] 을 stack에 삽입

3. arr[1] 부터는,  stack의 최상단의 값=가장 최근에 추가된 값(peek)이 arr[i]의 값과 일치여부 확인  후, 일치하지 않을 경우에만 stack에 해당 값 push  =>  이를 통해 중복되지 않은 값만 stack에 추가됨

4. answer의 사이즈는 stack의 사이즈와 동일하게 생성

5. stack의 사이즈만큼 반복하면서 stack에서 꺼낸 값들을 pop하여 담기

6. stack에서 꺼낸 값은 LIFO 이기 때문에 실제 배열의 역순이므로 그것의 역순으로 담아야 원래 순서가 됨

 

💡 스택 제공 연산 종류
pop() : 스택에서 가장 위에 있는 항목을 제거한다.
push(item) : item 하나를 스택의 가장 윗 부분에 추가한다.
peek() : 스택의 가장 위에 있는 항목을 반환한다.
isEmpty() : 스택이 비어 있을 때 true를 반환한다.

 

 

 

🔍 다른 사람의 풀이

import java.util.*;

public class Solution {
    public Stack<Integer> solution(int []arr) {

        Stack<Integer> stack = new Stack<>();

        for(int num : arr){
            if(stack.size() == 0 || stack.peek() != num){
                stack.push(num);
            }
        }

        return stack;
    }
}

 

리턴 타입을 바꾸면 이렇게 더 간단해지네요.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함