다음은 식품공장의 정보를 담은 FOOD_FACTORY 테이블입니다. FOOD_FACTORY 테이블은 다음과 같으며 FACTORY_ID, FACTORY_NAME, ADDRESS, TLNO는 각각 공장 ID, 공장 이름, 주소, 전화번호를 의미합니다.

Column nameTypeNullable
FACTORY_ID VARCHAR(10) FALSE
FACTORY_NAME VARCHAR(50) FALSE
ADDRESS VARCHAR(100) FALSE
TLNO VARCHAR(20) TRUE

문제

FOOD_FACTORY 테이블에서 강원도에 위치한 식품공장의 공장 ID, 공장 이름, 주소를 조회하는 SQL문을 작성해주세요. 이때 결과는 공장 ID를 기준으로 오름차순 정렬해주세요.


예시

FOOD_FACTORY 테이블이 다음과 같을 때

FACTORY_IDFACTORY_NAMEADDRESSTLNO
FT19980003 (주)맛있는라면 강원도 정선군 남면 칠현로 679 033-431-3122
FT19980004 (주)맛있는기름 경기도 평택시 포승읍 포승공단순환로 245 031-651-2410
FT20010001 (주)맛있는소스 경상북도 구미시 1공단로7길 58-11 054-231-2121
FT20010002 (주)맛있는통조림 전라남도 영암군 미암면 곤미현로 1336 061-341-5210
FT20100001 (주)맛있는차 전라남도 장성군 서삼면 장산리 233-1번지 061-661-1420
FT20100002 (주)맛있는김치 충청남도 아산시 탕정면 탕정면로 485 041-241-5421
FT20100003 (주)맛있는음료 강원도 원주시 문막읍 문막공단길 154 033-232-7630
FT20100004 (주)맛있는국 강원도 평창군 봉평면 진조길 227-35 033-323-6640
FT20110001 (주)맛있는밥 경기도 화성시 팔탄면 가재리 34번지 031-661-1532
FT20110002 (주)맛있는과자 광주광역시 북구 하서로 222 062-211-7759

SQL을 실행하면 다음과 같이 출력되어야 합니다.

FACTORY_IDFACTORY_NAMEADDRESS
FT19980003 (주)맛있는라면 강원도 정선군 남면 칠현로 679
FT20100003 (주)맛있는음료 강원도 원주시 문막읍 문막공단길 154
FT20100004 (주)맛있는국 강원도 평창군 봉평면 진조길 227-35

 


정답

SELECT FACTORY_ID, FACTORY_NAME, ADDRESS from FOOD_FACTORY  where ADDRESS LIKE '강원도%';

오늘의 학습

  • 특정 문자를 포함 할 때는 'LIKE' 연산자와 와일드카드 문자 '%'를 사용하여 특정 패턴이 포함된 데이터를 찾을 수 있다.
  • 위의 쿼리에서 '강원도%'는 '강원도'로 시작하는 모든 문자열을 의미한다. 따라서 이 쿼리는 ADDRESS 열에서 '강원도'로 시작하는 모든 행을 찾아 해당 행의 FACTORY_ID, FACTORY_NAME, ADDRESS를 반환한다.
  • 다른 와일드카드 문자로는 '_'가 있다. 이 문자는 임의의 단일 문자를 의미한다. 예를 들어, 'a_b'는 'acb', 'adb', 'aeb' 등 'a'와 'b' 사이에 임의의 문자가 있는 모든 문자열을 의미한다.

삼총사

💡 삼총사

문제 설명

한국중학교에 다니는 학생들은 각자 정수 번호를 갖고 있습니다. 이 학교 학생 3명의 정수 번호를 더했을 때 0이 되면 3명의 학생은 삼총사라고 합니다. 예를 들어, 5명의 학생이 있고, 각각의 정수 번호가 순서대로 -2, 3, 0, 2, -5일 때, 첫 번째, 세 번째, 네 번째 학생의 정수 번호를 더하면 0이므로 세 학생은 삼총사입니다. 또한, 두 번째, 네 번째, 다섯 번째 학생의 정수 번호를 더해도 0이므로 세 학생도 삼총사입니다. 따라서 이 경우 한국중학교에서는 두 가지 방법으로 삼총사를 만들 수 있습니다.

한국중학교 학생들의 번호를 나타내는 정수 배열 number가 매개변수로 주어질 때, 학생들 중 삼총사를 만들 수 있는 방법의 수를 return 하도록 solution 함수를 완성하세요.


제한사항

  • 3 ≤ number의 길이 ≤ 13
  • 1,000 ≤ number의 각 원소 ≤ 1,000
  • 서로 다른 학생의 정수 번호가 같을 수 있습니다.

입출력 예

number result

[-2, 3, 0, 2, -5] 2
[-3, -2, -1, 0, 1, 2, 3] 5
[-1, 1, -1, 1] 0

다른 코드

class Solution {
    public int solution(int[] number) {
        int answer = 0;
        for(int i=0; i<number.length;i++){
            for(int j=i+1;j<number.length;j++){
                for(int k=j+1; k<number.length;k++){
                    if(number[i] + number[j] + number[k] == 0) {
                        answer++;
                    }
                }
            }
        }
        return answer;
    }
}

i , j , k 로 각각 1,2,3 번째 수를 구하여 더한다. 이 중에 0이 되는 값이 있다면 anwer를 올린다.

 

시저암호

💡 시저 암호

문제 설명

어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.

제한 조건

  • 공백은 아무리 밀어도 공백입니다.
  • s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.
  • s의 길이는 8000이하입니다.
  • n은 1 이상, 25이하인 자연수입니다.

입출력 예

s n result

"AB" 1 "BC"
"z" 1 "a"
"a B z" 4 "e F d"

나의코드1

이 코드는 ‘A’와 ‘z’의 사잇값들을 전부 포함하므로 오류가 생긴다.

따라서 대소문자를 구분하여 나눈다.

class Solution {
   public String solution(String s, int n) {
        String answer = "";
        char[] chars = s.toCharArray();
        for(int i=0; i<chars.length;i++){
            if('A'<= chars[i]&&chars[i] <='z'){
                int charToInt = chars[i]+n;
                int i1 = charToInt - 26;
                if(charToInt>(int)'Z'&&charToInt<'a'){
                    chars[i] = (char) i1;
                } else if (charToInt>'z'){
                    chars[i] = (char) i1;
                } else{
                    chars[i] = (char) charToInt;
                }
            }
        }
        answer = new String(chars);
        return answer;
    }
}

테스트 케이스는 통과하나, 채점의 케이스에서는 몇개가 실패가 나온다.

나의코드2

class Solution {
   public String solution(String s, int n) {
        String answer = "";
        char[] chars = s.toCharArray();
        for(int i=0; i<chars.length;i++){
            int charToInt = chars[i]+n;
            int i1 = charToInt - 26;
            if('A'<= chars[i]&&'Z'>=chars[i]) {
                if (charToInt > 'Z') {
                    chars[i] = (char) i1;
                }else {
                    chars[i] = (char) charToInt;
                }
            }

            if('a'<=chars[i]&&'z'>=chars[i]){
                if (charToInt>'z'){
                    chars[i] = (char) i1;
                }else{
                    chars[i] = (char) charToInt;
                }
            }
        }
        answer = new String(chars);
        return answer;
    }
}

다른코드

originalChar가 ‘A’일때 아스키로는 65 이므로, (65-65+4) %26 +65 =69 이므로 D가 나온다.

originalChar-’A’를 하는것은 ‘A’부터 얼마만큼 큰 단어인지 확인하는 것이고, 이에 n을 더해 원하는 값을 만든다.

알파벳은 총 26자이므로, 26으로 나누었을때, 나머지가 있다면, 이는 ‘Z’보다 큰 값이다.

현재까지 나온 값((originalChar - 'A' + n) % 26))은 +n 값과 originalChar의 차이값이다.

그러므로 ‘A’에 차잇값을 더하여 원하는 값을 구한다.

class Solution {
    public String solution(String s, int n) {
        StringBuilder result = new StringBuilder();

        for (char originalChar : s.toCharArray()) {
            if (Character.isUpperCase(originalChar)) {
                char shiftedChar = (char) ((originalChar - 'A' + n) % 26 + 'A');
                result.append(shiftedChar);
            } else if (Character.isLowerCase(originalChar)) {
                char shiftedChar = (char) ((originalChar - 'a' + n) % 26 + 'a');
                result.append(shiftedChar);
            } else {
                result.append(originalChar);
            }
        }

        return result.toString();
    }
}

오늘의 학습 :

  • 모든 경우의 수에서 n만큼의 길이의 수를 구하려면 for문을 n번 반복하면 된다.
  • 값이 중복되지 않도록 각각의 변수에 +1을 해준다.
  • 대소문자 구분할때는 Character.isUpperCase(),LowerCase()를 사용하자

 

'프로그래머스 > 자바 코딩테스트' 카테고리의 다른 글

23-06-26  (0) 2023.06.26
23-06-24  (0) 2023.06.24
23-06-22  (0) 2023.06.22
23-06-20  (0) 2023.06.20
23-06-18  (0) 2023.06.18

크기가 작은 부분문자열

 💡 크기가 작은 부분문자열

문제 설명

숫자로 이루어진 문자열 t와 p가 주어질 때, t에서 p와 길이가 같은 부분문자열 중에서, 이 부분문자열이 나타내는 수가 p가 나타내는 수보다 작거나 같은 것이 나오는 횟수를 return하는 함수 solution을 완성하세요.

예를 들어, t="3141592"이고 p="271" 인 경우, t의 길이가 3인 부분 문자열은 314, 141, 415, 159, 592입니다. 이 문자열이 나타내는 수 중 271보다 작거나 같은 수는 141, 159 2개 입니다.


제한사항

  • 1 ≤ p의 길이 ≤ 18
  • p의 길이 ≤ t의 길이 ≤ 10,000
  • t와 p는 숫자로만 이루어진 문자열이며, 0으로 시작하지 않습니다.

입출력 예

t p result

"3141592" "271" 2
"500220839878" "7" 8
"10203" "15" 3

나의코드1

i의 크기가 t-p+1인 이유:

각 i 인덱스마다 p.length() 길이의 문자열을 검사해야 한다. 그러므로, 시작 인덱스(i)에서 **p.length()**를 더했을 때, 이 값이 **t.length()**를 넘어서면 안 된다. 즉, ‘i + p.length() <= t.length()’ 이어야 한다. 그래서 반복문의 조건은 **i < t.length() - p.length() + 1**이 된다.

 import java.util.*;
class Solution {
    public int solution(String t, String p) {
        int answer = 0;
        ArrayList<String> list = new ArrayList<>();
        char [] tToChar = t.toCharArray();
        StringBuilder stringBuilder = null;
        for(int i=0;i<tToChar.length-p.length()+1;i++){
            stringBuilder = new StringBuilder();
            for(int j=i;j<p.length()+i;j++){
                stringBuilder.append(tToChar[j]);
            }
            list.add(stringBuilder.toString());
        }
        ArrayList<String> list1 = list;
        for (String s : list1) {
            if(Integer.parseInt(s)<=Integer.parseInt(p)){
                answer++;
            }
        }
        return answer;
    }
}

코드 자체는 동작하지만, 채점단계에서 런타임 오류가 발생한다.

나의코드2

s의 값과, p의 값이 int의 최대표현값을 넘어가는 경우가 있어서 런타임 오류가 발생했었다.

import java.util.*;
class Solution {
    public int solution(String t, String p) {
        int answer = 0;
        ArrayList<String> list = new ArrayList<>();
        char [] tToChar = t.toCharArray();
        StringBuilder stringBuilder = null;
        for(int i=0;i<tToChar.length-p.length()+1;i++){
            stringBuilder = new StringBuilder();
            for(int j=i;j<p.length()+i;j++){
                stringBuilder.append(tToChar[j]);
            }
            list.add(stringBuilder.toString());
        }
        ArrayList<String> list1 = list;
        for (String s : list1) {
            if(Long.parseLong(s)<=Long.parseLong(p)){
                answer++;
            }
        }
        return answer;
    }
}

다른코드1

import java.util.*;
class Solution {
     public static int solution(String t, String p) {
       int answer = 0;
    Long pValue = Long.parseLong(p);
    for(int i = 0; i <= t.length() - p.length(); i++){
        String sub = t.substring(i, i + p.length());
        if(Long.parseLong(sub) <= pValue){
            answer++;
        }
    }
    return answer;
    }
}

subString을 이용해 간결하게 표현한 코드다.

다른코드2

import java.util.stream.LongStream;

class Solution {
    public int solution(String t, String p) {
        long targetNumber = Long.parseLong(p);
        int targetNumberLength = p.length();

        return (int) LongStream.range(0L, t.length() - targetNumberLength + 1L)
                .mapToObj(i -> t.substring((int) i, (int) i + targetNumberLength))
                .mapToLong(Long::parseLong)
                .filter(number -> number <= targetNumber)
                .count();
    }
}

이건 위의 과정을 stream으로 변형한 방법이다.

 

오늘의 학습 :

  • 문자열 전체에서 존재할 수 있는 특정 길이만큼의 문자열을 모두 확인 할 필요가 있을땐 subString을 사용하자

'프로그래머스 > 자바 코딩테스트' 카테고리의 다른 글

23-06-27  (0) 2023.06.27
23-06-24  (0) 2023.06.24
23-06-22  (0) 2023.06.22
23-06-20  (0) 2023.06.20
23-06-18  (0) 2023.06.18

이상한 문자 만들기

💡 이상한 문자 만들기

문제 설명

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

제한 사항

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

입출력 예

s return

"try hello world" "TrY HeLlO WoRlD"

입출력 예 설명

"try hello world"는 세 단어 "try", "hello", "world"로 구성되어 있습니다. 각 단어의 짝수번째 문자를 대문자로, 홀수번째 문자를 소문자로 바꾸면 "TrY", "HeLlO", "WoRlD"입니다. 따라서 "TrY HeLlO WoRlD" 를 리턴합니다.

코드1

import java.util.*;

class Solution {
    public String solution(String s) {
      StringBuilder stringBuilder = new StringBuilder();
    int idx = 0;
    for (char c : s.toCharArray()) {
        if (c == ' ') {
            stringBuilder.append(c);
            idx = 0;
        } else {
            stringBuilder.append(idx % 2 == 0 ? Character.toUpperCase(c) : Character.toLowerCase(c));
            idx++;
        }
    }
    return stringBuilder.toString();
}
}
  1. c가 공백이 아닐때는 idx를 통하여 자리가 홀수인지 짝수인지 구분하여 대소문자를 구분한다.
  2. c가 공백이라면, 빌더에 추가한 후 idx를 초기화한다. 이렇게 하면 각 단어들의 인덱스를 구분할 수있다.

3진법 뒤집기

 💡 3진법 뒤집기

문제 설명

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


제한사항

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

입출력 예

n result

45 7
125 229

나의 코드

class Solution {
    public int solution(int n) {
        int answer= 0;
        String step1 = Integer.toString(n,3);
        String step2 = new StringBuilder(step1).reverse().toString();
        return Integer.parseInt(step2,3);
    }
}

오늘의 학습 :

  • 숫자 number를 10진수에서 n진수로 변환하려면 Intger.toString(number,n)으로 하면 변환된다.
  • StringBuilder는 문자열을 뒤집을때 유용하다.
  • n진수 nNumber를 10진수로 변환하려면 Integer.parseInt(nNumber,n); 로 하면 된다.

'프로그래머스 > 자바 코딩테스트' 카테고리의 다른 글

23-06-27  (0) 2023.06.27
23-06-26  (0) 2023.06.26
23-06-22  (0) 2023.06.22
23-06-20  (0) 2023.06.20
23-06-18  (0) 2023.06.18

같은 숫자는 싫어

💡 같은 숫자는 싫어

문제 설명

배열 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]

입출력 예 설명

입출력 예 #1,2

문제의 예시와 같습니다.

코드1

import java.util.*;

public class Solution {
    public int[] solution(int []arr) {
            ArrayList<Integer> list = new ArrayList<>();
            
            for(int i=0; i<arr.length-1; i++) {
                if(arr[i] != arr[i+1]) {
                    list.add(arr[i]);
                }
            }

            // 마지막 요소는 항상 추가
            list.add(arr[arr.length-1]);

            // ArrayList를 배열로 변환
            int[] answer = list.stream().mapToInt(i -> i).toArray();

            return answer;
        }
}

arr.length의 -1 은 밑에 arr[i]+1 이기 때문에 추가했다.

그리고 항상 마지막 요소는 add하지 않기때문에 마지막에 add를 해준다.

최대공약수와 최소공배수

💡 최대공약수와 최소공배수

문제 설명

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

제한 사항

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

입출력 예

n m return

3 12 [3, 12]
2 5 [1, 10]

입출력 예 설명

입출력 예 #1

위의 설명과 같습니다.

입출력 예 #2

자연수 2와 5의 최대공약수는 1, 최소공배수는 10이므로 [1, 10]을 리턴해야 합니다.

코드1

class Solution {
    public int[] solution(int n, int m) {
        int[] answer = new int[2];

        int gcd = findGCD(n, m);
        int lcm = (n * m) / gcd;

        answer[0] = gcd;
        answer[1] = lcm;
        return answer;
    }

    public int findGCD(int a, int b) {
        if (b == 0)
            return a;
        else
            return findGCD(b, a % b);
    }
}

GCD(최대공약수) 를 먼저 구한 후 최대공약수를 이용하여 LCM(최소공배수를) 구한다.

return findGCD(b, a % b); b가 a보다 클 경우에는 나머지가 a가 되므로 a가 최대공약수가 된다.

  • 최대공약수 공식 : (b, a%b)
  • 최소공배수 공식 : (n*m) / 최대공약수

오늘의 학습 :

  • 최소공배수는 두 수의 곱에 최대공약수를 나누면 나온다.
  • 최대공약수는 (b, a%b) 이다.
  • a%b에서 b가 a보다 크면 나머지는 a가 된다.

'프로그래머스 > 자바 코딩테스트' 카테고리의 다른 글

23-06-26  (0) 2023.06.26
23-06-24  (0) 2023.06.24
23-06-20  (0) 2023.06.20
23-06-18  (0) 2023.06.18
23-06-17  (0) 2023.06.17

행렬의 덧셈

💡

문제 설명

행렬의 덧셈은 행과 열의 크기가 같은 두 행렬의 같은 행, 같은 열의 값을 서로 더한 결과가 됩니다. 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][arr1[0].length];
        for(int i=0; i<arr1.length;i++){
            for(int k=0; k<arr1[i].length;k++){
                answer[i][k] = arr1[i][k]+arr2[i][k];
            }
        }
        return answer;
    }
}

여기서 나는 더 줄일것이 없다고 생각했는데.

다른코드1

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

이런식으로 answer를 arr1으로 지정하고

answer[i][k]에 += arr2[i][k] 하는식으로 코드를 줄일수있었다.

  • 위 코드를 사용하면 새로운 객체를 사용하는것이 아닌 기존의 다중배열 arr1을 참조하는것이기 때문에 공간복잡도를 줄일 수 있다.
  • 공간복잡도를 줄이면 메모리를 절약할 수 있다.
  • 하지만 arr1의 원본 데이터를 수정하므로 ‘캡슐화’ 원칙을 어기게 된다.

성능상 효율차이는 거의 없을것같지만 코드가 더욱 간결해졌다는 점이 눈에 띈다.

 

직사각형 별찍기

💡

문제 설명

이 문제에는 표준 입력으로 두 개의 정수 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("");
        }
    }
}
  • Scanner sc = new Scanner(System.in); 는 콘솔입력(System.in)을 파라미터로 갖는 Scanner 객체를 생성한다.
  • nextInt()는 입력값을 공백으로 구분된 토큰으로 처리한다. “5 4” 는 5와 4로, “54”는 54로 처리한다.

다른코드1

StringBuilder,IntStream 사용

import java.util.Scanner;
import java.util.stream.IntStream;

public class Solution {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();

        StringBuilder sb = new StringBuilder();
        IntStream.range(0, a).forEach(s -> sb.append("*"));
        IntStream.range(0, b).forEach(s -> System.out.println(sb.toString()));
    }
}
  • IntStream은 Int 전용 Stream객체이다. IntStream 외에도 LongStream,DoubleStream이 존재한다.
  • IntStream에서는 range또는 rangeClosed 메소드를 통해 정수범위를 지정할 수 있다. 또한 sum , average, max, min 과 같은 집계 함수가 가능하다.
  • 0부터 a-1 까지 StringBuilder에 *을 추가하고, 0부터 b까지 StringBuilder에 쌓아둔 *을 b만큼 println으로 반복한다.

다른코드2

Stream 사용

import java.util.Scanner;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Solution {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();

        String stars = IntStream.range(0, a).mapToObj(i -> "*").collect(Collectors.joining());
        IntStream.range(0, b).forEach(i -> System.out.println(stars));
    }
}
  • mapToObj(i→””).collect(Collectors.joining()) : 0부터a-1까지 요소 i를 “”로 치환하고 하나로 합친다.
  • 이후 b만큼 반복하여 합친”*”를 출력한다.

오늘의 학습 :

  • 공간복잡도를 줄이면 메모리를 절약할 수 있다.
  • 캡슐화 : 객체의 상태를 외부에서 직접 변경할 수 없도록 보호하는 것
  • Scanner sc = new Scanner(System.in); 는 콘솔입력(System.in)을 파라미터로 갖는 Scanner 객체를 생성한다.
  • nextInt()는 입력값을 공백으로 구분된 토큰으로 처리한다. “5 4” 는 5와 4로, “54”는 54로 처리한다.
  • IntStream은 Int 전용 Stream객체이다. IntStream 외에도 LongStream,DoubleStream이 존재한다.
  • IntStream에서는 range()또는 rangeClosed() 메소드를 통해 정수범위를 지정할 수 있다. 또한 sum() , average(), max(), min() 과 같은 집계 함수가 가능하다.
  • mapToObj()는 원시타입(int 등)을 참조형 스트림(Integer 등 )으로 변환할때 유용하다.

'프로그래머스 > 자바 코딩테스트' 카테고리의 다른 글

23-06-24  (0) 2023.06.24
23-06-22  (0) 2023.06.22
23-06-18  (0) 2023.06.18
23-06-17  (0) 2023.06.17
23-06-16  (0) 2023.06.16

문자열 다루기 기본

💡 문제 설명

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

제한 사항

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

입출력 예

s return

"a234" false
"1234" true

나의 코드

import java.util.*;
import java.util.stream.*;
class Solution {
    public boolean solution(String s) {
        if(s.length() == 4 || s.length()== 6){

            try{
                Stream.of(s).mapToInt(Integer::parseInt).toArray();
            return true;
            }catch (NumberFormatException e){
                return false;
            }
        }
                return false;
            }
}

stream으로 int [] 로 변환했을때 numberFormatException이 뜨면 string의 문자열이 온전히 숫자가 아니므로 try-catch로 값을 변환시켰다.

문자 길이의 제한이 있다는것을 알지 못해서 헤매었다.

다른코드1

class Solution {
  public boolean solution(String s) {
      if(s.length() == 4 || s.length() == 6){
          try{
              int x = Integer.parseInt(s);
              return true;
          } catch(NumberFormatException e){
              return false;
          }
      }
      else return false;
  }
}

stream만 생각하니 단순히 s를 Integer.parseInt할수있다는것을 잊었다.

그 외 기본적인 흐름은 나와 같은것같다.

다른코드2

public boolean solution(String s) {
    return (s.length() == 4 || s.length() == 6) && s.chars().allMatch(Character::isDigit);
}

allMatch() 는 스트림의 모든 요소가 해당조건을 만족하는 경우 true를 반환

조건문을 제시할수도 있다

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allLessThanTen = numbers.stream().allMatch(n -> n < 10);

문자열 내림차순으로 배치하기

💡 문자열 내림차순으로 배치하기

문제 설명

문자열 s에 나타나는 문자를 큰것부터 작은 순으로 정렬해 새로운 문자열을 리턴하는 함수, solution을 완성해주세요.

s는 영문 대소문자로만 구성되어 있으며, 대문자는 소문자보다 작은 것으로 간주합니다.

제한 사항

  • str은 길이 1 이상인 문자열입니다.

입출력 예

s return

"Zbcdefg" "gfedcbZ"

나의 코드

import java.util.*;
import java.util.stream.Collectors;
class Solution {
     public String solution(String s) {
                String[] split = s.split("");
                List<String> collect = Arrays.stream(split).sorted().collect(Collectors.toList());
                Collections.reverse(collect);
                StringBuilder stringBuilder = new StringBuilder();
                for (String answer : collect) {
                    stringBuilder.append(answer);
                }
                return stringBuilder.toString();
            }
}

개선 코드

import java.util.*;
import java.util.stream.*;
class Solution {
    public String solution(String s) {
               return Stream.of(s.split(""))
                       .sorted(Comparator.reverseOrder())
                       .collect(Collectors.joining());

            }
}

Stream을 이런식으로 따로 호출할수있는줄 몰랐다.

그리고 stream에서 다로 역정렬이 가능한지 몰랐다.

joining은 문자열을 합치는것.

코딩테스트를 풀면서 stream 범용적으로 많은 작업을 수행할수있다는것을 느낀다.

하지만 불변객체이기 때문에 메모리 효율은 떨어진다.

다른코드1

public String reverseStr(String str){
        char[] sol = str.toCharArray();
    Arrays.sort(sol);
    return new StringBuilder(new String(sol)).reverse().toString();
    }

tocharArray를 사용하여 정렬을하고 Stringbuilder에 넣고 역정렬하여 반환했다.

나는 .split(””) 을 하여 StringBuilder에 넣으려니 파라미터가 맞지 않아서 어려웠는데, toCharArray를 하면 반환형이 String[] 가 아닌 char[] 라서 쉽게 가능하다.

오늘의 학습 :

  • Stream.of() 는 배열이나 항목을 스트림으로 전환한다.
  • sorted(Comparator.reverseOrder())는 역순으로 정렬한다.
  • Collectors.joining()은 스트림의 모든 문자를 문자열로 합친다.
  • StringBuilder에서는 reverse()는 가능하지만 sort같은 정렬기능은 없다.
  • split(””) 은 String[] 를 리턴하므로 StringBuilder에 사용하기에는 적합하지 않다.
  • toCharArray()를 사용하면 반환형이 char[] 이다. 이는 StringBuilder에서 사용이 가능하다.
  • String이 반환형일때는 StringBuilder로 반환해도 괜찮다.
  • 스트링객체.chars() 는 intStream 객체를 반환
  • allMatch(조건) 는 스트림 요소 중 모든 요소들이 조건에 부합해야 참을 반환

'프로그래머스 > 자바 코딩테스트' 카테고리의 다른 글

23-06-22  (0) 2023.06.22
23-06-20  (0) 2023.06.20
23-06-17  (0) 2023.06.17
23-06-16  (0) 2023.06.16
23-06-14  (0) 2023.06.14

 

내적

💡 문제 설명

길이가 같은 두 1차원 정수 배열 a, b가 매개변수로 주어집니다. a와 b의 내적을 return 하도록 solution 함수를 완성해주세요.

이때, a와 b의 내적은 a[0]*b[0] + a[1]*b[1] + ... + a[n-1]*b[n-1] 입니다. (n은 a, b의 길이)


제한사항

  • a, b의 길이는 1 이상 1,000 이하입니다.
  • a, b의 모든 수는 -1,000 이상 1,000 이하입니다.

입출력 예

a b result

[1,2,3,4] [-3,-1,0,2] 3
[-1,0,1] [1,0,-1] -2

내 코드

class Solution {
    public int solution(int[] a, int[] b) {
        int answer = 0;
        for(int i=0; i<a.length;i++){
           answer+= a[i] * b[i];
        }
        return answer;
    }
}

약수의 개수와 덧셈

💡 문제 설명

두 정수 left와 right가 매개변수로 주어집니다. left부터 right까지의 모든 수들 중에서, 약수의 개수가 짝수인 수는 더하고, 약수의 개수가 홀수인 수는 뺀 수를 return 하도록 solution 함수를 완성해주세요.


제한사항

  • 1 ≤ left ≤ right ≤ 1,000

입출력 예

left right result

13 17 43
24 27 52

나의 코드

import java.util.*;
class Solution {
   public int solution(int left, int right) {
                int count=0;
                ArrayList<Integer> list = new ArrayList<>();
                for(int i=left; i<right+1;i++){
                    count = 0;
                    for(int j =1; j<i+1;j++){
                        if(i%j==0){
                            count++;
                        }
                    }
                    if(count%2!=0){
                        list.add(-i);
                    }else{
                        list.add(i);
                    }

                }
                return list.stream().mapToInt(Integer::intValue).sum();
            }
}

개선 :

3항연산자로 변경.

public int solution(int left, int right) {
                int count=0;
                ArrayList<Integer> list = new ArrayList<>();
                for(int i=left; i<right+1;i++){
                    count = 0;
                    for(int j =1; j<i+1;j++){
                        if(i%j==0){
                            count++;
                        }
                    }
                    list.add(count%2!=0?-i:i);
                }
                return list.stream().mapToInt(Integer::intValue).sum();
            }

다른코드1 :

i의 값이 i의 제곱근으로 나누어지는 경우 : 즉, 한 숫자의 값으로 i의 값이 나온다면,

배열의 개수는 홀수이므로 i를 음수처리한다. 반대라면 i를 양수처리한다.

class Solution {
    public int solution(int left, int right) {
        int answer = 0;

        for (int i=left;i<=right;i++) {
            //제곱수인 경우 약수의 개수가 홀수
            if (i % Math.sqrt(i) == 0) {
                answer -= i;
            }
            //제곱수가 아닌 경우 약수의 개수가 짝수
            else {
                answer += i;
            }
        }

        return answer;
    }
}

이건 문제 예시 패턴을 보고 유추할수있는 부분이였다.

이 부분을 캐치하고 적용한 점이 놀랍다.

다른코드2:

Math.sqrt(i)의 값은 실수형이므로, 정수형으로 바꾼것과 기존의 값이 같다면, 즉 i에게 제곱근이 존재한다면, 홀수, 아니면 짝수

import java.util.stream.IntStream;

class Solution {
    public int solution(int left, int right) {
        return IntStream.rangeClosed(left, right)
                        .map(i -> Math.sqrt(i) == (int) Math.sqrt(i) ? -i : i)
                        .sum();
    }
}

오늘의 학습 :

  • 제곱한 값(i*i)의 약수는 홀수이다.
  • Math.sqrt(i) 는 실수형(double)을 리턴한다.
  • IntStream.rangeClosed(left,right) 라는함수는 left와,right 사이의 연속된 정수 스트림을 생성한다.

'프로그래머스 > 자바 코딩테스트' 카테고리의 다른 글

23-06-22  (0) 2023.06.22
23-06-20  (0) 2023.06.20
23-06-18  (0) 2023.06.18
23-06-16  (0) 2023.06.16
23-06-14  (0) 2023.06.14

가운데 글자 가져오기

💡 단어 s의 가운데 글자를 반환하는 함수, solution을 만들어 보세요. 단어의 길이가 짝수라면 가운데 두글자를 반환하면 됩니다.

재한사항

  • s는 길이가 1 이상, 100이하인 스트링입니다.

입출력 예

s return

"abcde" "c"
"qwer" "we"

나의 코드

import java.util.*;
class Solution {
   public String solution(String s) {
                //s의 짝수/홀수를 구분
                //s의 가운데 위치를 구분
                String[] split = s.split("");
                if(split.length%2!=0){
                        int i1 = (split.length - 1) / 2;
                    return split[i1];

                }else{
                    int i = split.length / 2;
                    return split[i-1]+split[i];
                
            }
}
}

다른코드1

String getMiddle(String word){
return word.substring((word.length()-1)/2, word.length()/2 + 1);
    }

스트링.substring(int beginIndex, int endIndex**)**는 geginIndex ≤x <endIdex의 관계이다.

자바에서 정수의 나눗셈은 항상 버림이기 때문에, word.length()-1의 값이 정수이면 그냥두고, 소수이면 버림한다.

정수 : 길이가 6인 문자열을 입력했을때, 시작인덱스는 2가되고 끝 인덱스는 4가되버린다.

즉 x는 2,3이 되어버려서 2글자가 리턴된다.

홀수 : 길이가 5인 문자열을 입력했을때, 시작인덱스는 2가되고 끝인덱스는 3이된다

즉, x는 2가 되어 1글자가 리턴된다.

 

위 코드는 좀 감탄스럽다. substring으로 이렇게 간단하게 압축할수있을줄은 몰랐다.

 


수박수박수박수박수박수?

💡 문제 설명

길이가 n이고, "수박수박수박수...."와 같은 패턴을 유지하는 문자열을 리턴하는 함수, solution을 완성하세요. 예를들어 n이 4이면 "수박수박"을 리턴하고 3이라면 "수박수"를 리턴하면 됩니다.

제한 조건

  • n은 길이 10,000이하인 자연수입니다.

입출력 예

n return

3 "수박수"
4 "수박수박"

나의코드

import java.util.*;
class Solution {
     public String solution(int n) {
                String[] answer =new String [n];
                for(int i=0;i<n;i++){
                  answer[i] = (i%2==0 ? "수" :  "박");
                }
                return String.join("",answer);
            }
}

다른코드1

public class WaterMelon {
    public String watermelon(int n){

        return new String(new char [n/2+1]).replace("\\0", "수박").substring(0,n);
    }

단어의 크기만 지정된 char 배열을 만든다. 만약 n이 3이면 [null,null] 이 생성된다.

replace 함수로 null을 “수박”으로 교체한다. 여기서 “\0”은 문자열로 표현한 null 이다.

그 후 substring 으로 배열을 자르면, 0<x<3이 되므로 “수박수”가 된다.

이 코드는 간결성은 좋지만, 한눈에 알아보기가 힘들다.

 

다른코드2

public String solution(int n) {
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < n; i++){
            sb.append((i % 2 == 0) ? "수" : "박");
        }
        return sb.toString();
    }
}

이 코드는 StringBuilder와 3항연산자를 이용했다.

i의 값이 짝수면 “수”를 추가, 홀수면 “박”을 추가한다.

Stringbuilder는 가변이므로, String처럼 계속 객체를 생성할 필요가 없으므로 효율적이다.

 

오늘의 학습

  • 스트링 자체에서 substring이라는 함수가 범위를 지정할수있다는것을 알았다.
  • 단순 정수는 값을 나누었을때 소숫점으로 나누어지면 버림을 한다는것을 알게 되었다.
  • String은 char의 배열로 이루어졌다는것을 알았다.
  • null을 문자열로 표현할때는 “\0”이라는것을 알았다.
  • StringBuilder는 가변객체, String은 불변 객체라는것을 알았다.

'프로그래머스 > 자바 코딩테스트' 카테고리의 다른 글

23-06-22  (0) 2023.06.22
23-06-20  (0) 2023.06.20
23-06-18  (0) 2023.06.18
23-06-17  (0) 2023.06.17
23-06-14  (0) 2023.06.14

음양 더하기

💡 어떤 정수들이 있습니다. 이 정수들의 절댓값을 차례대로 담은 정수 배열 absolutes와 이 정수들의 부호를 차례대로 담은 불리언 배열 signs가 매개변수로 주어집니다. 실제 정수들의 합을 구하여 return 하도록 solution 함수를 완성해주세요.

 

나의 코드 :

class Solution {
    public int solution(int[] absolutes, boolean[] signs) {
        //solution 배열의 값을 확인한다.
        //만약 signs의 값이 true면 양수, false면 음수를 뜻한다.
        // 구해진 값을 모두 합해서 리턴    
        int answer = 0;
        for(int i=0; i<absolutes.length;i++){
            if(signs[i]==false){
                absolutes[i]=-absolutes[i];
            }
            answer += absolutes[i];
            
        }
        return answer;
    }
}

코드1 :

class Solution {
    public int solution(int[] absolutes, boolean[] signs) {
        int answer = 0;
        int arrLength = absolutes.length;

        for(int i=0;i<arrLength;i++){
            if(signs[i]){
                answer += absolutes[i];
            }else{
                answer -= absolutes[i];
            }
        }

        return answer;
    }
}

이 코드에서는 signs의 타입형태를 이용했다.

그래서 signs[i]의 값이 true이면 answer에 더하고,

signs[i]값이 false이면 answer에서 값을 뺀다.

내 코드에는 한쪽의 조건만 명시함에 비해

이 코드는 간결하게 true일때와, false일때를 명시했다.

코드2:

class Solution {
    public int solution(int[] absolutes, boolean[] signs) {
        int answer = 0;
        for (int i=0; i<signs.length; i++)
            answer += absolutes[i] * (signs[i]? 1: -1);
        return answer;
    }
}

이 코드는 삼항연산자를 이용해서 코드를 if문을 따로 적지 않고 표현했다.

signs 자체를 true냐 false냐 라는 조건식을 통해서 absolute[i]에 1을 곱하느냐, -1을 곱하느냐,

즉 양수냐 음수냐를 정해서 answer에 더한다.

앞서 두 코드를 보면서 signs[i] 자체를 조건문으로 보고 코드를 짰다는것이 새로웠다.

또 마지막코드에서는 양수, 음수를 1과 -1로 구분하여 absolutes[i]에 곱하여 양,음수를 구현했다는것이 새로웠다.

내 코드는 필요한것만 적어서 직관적으로 보였고

두번째 코드는 양수인 조건, 음수인 조건을 모두 명시하여 명확하고 직관적으로 보였고

세번째 코드는 삼항연산자가 익숙하지 않은 나에게는 읽는데 익숙하지는 않아 한번에 보기는 힘들었지만, 코드가 간결하고 아이디어가 참신했다.

하지만 어떤 코드가 좋은 코드인지는 잘 모르겠다. 

삼항연산자를 쓴 코드가 가장 간결하며 직관적이지만

삼항연산자가 익숙하지 않은 나에게는 두번째 코드가 더 명확하게 다가온다.

그렇다면 무엇이 더 좋은 코드일까?

초보자도 알아볼수있어야 좋은 코드일까?

어떻게 해야 나도 좋은 코드를 만들 수 있을까?

 

제일 작은 수 제거하기

💡 정수를 저장한 배열, arr 에서 가장 작은 수를 제거한 배열을 리턴하는 함수, solution을 완성해주세요. 단, 리턴하려는 배열이 빈 배열인 경우엔 배열에 -1을 채워 리턴하세요. 예를들어 arr이 [4,3,2,1]인 경우는 [4,3,2]를 리턴 하고, [10]면 [-1]을 리턴 합니다.

 

import java.util.*;
class Solution {
    public int[] solution(int[] arr) {
        if (arr.length == 1) return new int[]{-1}; // 배열의 길이가 1이면 -1을 반환

        int min = Arrays.stream(arr).min().getAsInt(); // 배열에서 최소값 찾기
        return Arrays.stream(arr).filter(i -> i != min).toArray(); // 최소값이 아닌것들만 배열생성
    }
}

여기서 filter() 는 조건문이 참인 경우를 구현한다.

만약 참과 거짓에 따른 결과를 다르게 두려면 boxed()로 Wrapper 클래스로 변환하여 map() 사용해서 람다를 구현한다.

public int[] solution(int[] arr) {
    int min = Arrays.stream(arr).min().getAsInt(); // 배열에서 최소값 찾기
    int[] minArray = Arrays.stream(arr).filter(i -> i != min).toArray(); // 최소값을 제외하고 새 배열 생성
    return  minArray.length == 0 ? new int[]{-1} : minArray; // 배열의 길이가 0이면 -1을 반환하고, 그렇지 않으면 필터링 된 배열을 반환
}

정리

  • filter()는 특정 조건이 만족하는 요소만 선택하여 새로운 스트림을 만든다.
  • map()은 각 요소에 특정 함수를 적용하여 그 결과를 기반으로 새로운 스트림을 만든다.
    • 기본형에는 map이 불가능하므로 Wrapper 클래스로 변한한다.

'프로그래머스 > 자바 코딩테스트' 카테고리의 다른 글

23-06-22  (0) 2023.06.22
23-06-20  (0) 2023.06.20
23-06-18  (0) 2023.06.18
23-06-17  (0) 2023.06.17
23-06-16  (0) 2023.06.16

+ Recent posts