본문 바로가기
개인 프로젝트/JAVA 학습

프로그래머스 Java 오답노트

by 황밤 2023. 8. 16.
728x90
반응형

0816

 

 

1. 

정수 리스트num_list와 정수n이 주어질 때,num_list의 첫 번째 원소부터n 번째 원소까지의 모든 원소를 담은 리스트를 return하도록 solution 함수를 완성해주세요.

 

class Solution {
    public int[] solution(int[] num_list, int n) {
        int[] answer = {};
        answer = new int[n]; //n개의 저장장소를 만든다
        for(int i=0; i<n; i++) {
            answer[i] = num_list[i];
        }
        return answer;
    }
}

오답요인 : answer = new int[n]을 선언해주지 않음. 즉 answer라는 배열에 공간을 할당해주지 않았음.

 

 


 

2.

 

 

정수 n과 문자열 control이 주어집니다. control은 "w", "a", "s", "d"의 4개의 문자로 이루어져 있으며, control의 앞에서부터 순서대로 문자에 따라 n의 값을 바꿉니다.

  • "w" : n이 1 커집니다.
  • "s" : n이 1 작아집니다.
  • "d" : n이 10 커집니다.
  • "a" : n이 10 작아집니다.

위 규칙에 따라 n을 바꿨을 때 가장 마지막에 나오는 n의 값을 return 하는 solution 함수를 완성해 주세요.

 

class Solution {
    public int solution(int n, String control) {
        int answer = 0;
        int len = control.length();
        
        for(int i=0;i<len;i++){
            if(control.charAt(i)=='w'){
                n = n + 1;
            }
            else if(control.charAt(i)=='s'){
                n = n - 1;
            }
            else if(control.charAt(i)=='d'){
                n = n + 10;
            }
            else if(control.charAt(i) == 'a'){
                n = n - 10;
            }
            
            else {
                n = n;
            }
        answer = n;
        }
        return answer;
    }
}

자바는 다른 프로그래밍 언어와 달리 문자열을 표현할 때 큰 따옴표(")와 작은 따옴표가 구분된다. 큰 따옴표는 일반적인 쓰임새와 같고(string 자료형), 작은 따옴표는 단 하나의 문자만 담을 수 있다(char 자료형).

 

"" 큰 따음표를 사용하여 문자열을 기대하게 하여 정답이 나오지 않았다. "w" 가 아니라 'w'로 써야함.

 


 

3.

 

문자열 배열 strlist가 매개변수로 주어집니다. strlist 각 원소의 길이를 담은 배열을 retrun하도록 solution 함수를 완성해주세요

 

class Solution {
    public int[] solution(String[] strlist) {
        int[] answer = {};
        answer = new int[strlist.length];
        
        for(int i=0; i<strlist.length; i++){
            String a = new String(strlist[i]);
            
            int b = a.length();
            
            answer[i] = b;
        }
        return answer;
    }
}
틀린 부분 : int 배열의 경우 -> 배열.length 로 길이를 구할 수 있으나,
문자열의 길이 같은 경우 -> 문자열.length가 아닌, 문자열.length()를 해주어야 했다. !!

4. 

함수 solution은 정수 x와 자연수 n을 입력 받아, x부터 시작해 x씩 증가하는 숫자를 n개 지니는 리스트를 리턴해야 합니다. 다음 제한 조건을 보고, 조건을 만족하는 함수, solution을 완성해주세요

class Solution {
    public long[] solution(int x, int n) {
        long[] answer = {};
        answer = new long[n];
        
        for(int i=0; i<n; i++){
            answer[i] = (long) (i+1)*x;
        
        }
        return answer;
    }
}

 

answer[i] = (i+1)*x; 에서 (long)으로 형변환 해주지 않았었던 것이 오답의 원인!

 

 

 


6.

 

int or long 등의 정수 형의 자리수를 구하는 방법?!!?!

 

int num = 12345;

int length = (int)(Math.log10(num)+1);

System.out.println("결과 : " + length);

// 결과 : 5

이런 식으로 구할 수 있습니다!!

 

 

 


7. 

대문자와 소문자가 섞여있는 문자열 s가 주어집니다. s에 'p'의 개수와 'y'의 개수를 비교해 같으면 True, 다르면 False를 return 하는 solution를 완성하세요. 'p', 'y' 모두 하나도 없는 경우는 항상 True를 리턴합니다. 단, 개수를 비교할 때 대문자와 소문자는 구별하지 않습니다.

 

예를 들어 s가 "pPoooyY"면 true를 return하고 "Pyy"라면 false를 return합니다.

class Solution {
    boolean solution(String s) {
        boolean answer = true;
        int p = 0;
        int y = 0;
        int n = s.length();
        char c = 0;
    
        for(int i=0; i<n; i++){
            c = s.charAt(i);
            if(c == 'p' || c == 'P'){
                p += 1;
                
            }else if(c == 'y' || c == 'Y'){
                y += 1;
            
            }
        }    
        
        if(p == y) {
            answer = true;
        }
        else{
            answer = false;
        }
        

        return answer;
    }
}
오답 원인 : 우선 처음 charAt를 사용하여 String s 의 각 알파벳 처음 부터 끝까지를 비교하여 true, false를 출력할려고 하였다. 그러나  charAt는 char의 형태로 return 해주기 때문에, 뒤에 비교 대상 y, Y 등을 ""이 아닌 ''로 감싸야 했었다. 이를 실패하고, String[] str = s.split("") 을 사용해 진행하려고 하였으나, 문제 해결이 되지 않았다.

결국 다시 charAt()를 사용하여, 'y', 'p'로 비교를 통한 값의 비교를 이용해 해결할 수 있었다.

 

 


8.

 

문제 :괄호가 바르게 짝지어졌다는 것은 '(' 문자로 열렸으면 반드시 짝지어서 ')' 문자로 닫혀야 한다는 뜻입니다. 예를 들어

  • "()()" 또는 "(())()" 는 올바른 괄호입니다.
  • ")()(" 또는 "(()(" 는 올바르지 않은 괄호입니다.

'(' 또는 ')' 로만 이루어진 문자열 s가 주어졌을 때, 문자열 s가 올바른 괄호이면 true를 return 하고, 올바르지 않은 괄호이면 false를 return 하는 solution 함수를 완성해 주세요.

class Solution {
    boolean solution(String s) {
        boolean answer = true;
        int n = s.length();
        int sum1 = 1;
        int sum2 = 0;
        if(s.charAt(0) =='(' && s.charAt(n-1) == ')'){
            while(sum1 >= sum2){    
                for(int i=1;i<n;i++){
                
                    if(s.charAt(i) == '('){
                        sum1 += 1;
                    }else if(s.charAt(i) == ')'){
                        sum2 += 1;
                    }
                }
            }
            if(sum1 == sum2){
                answer = true;  // ())(() 반례 확인 필요
            }else if(sum1 != sum2){
                answer = false;
            }
        }
        else if(n <= 0){
            answer = false;
        }
        else if(n % 2 == 1){
            answer = false;
        }
        else{
            answer = false;
        }

        return answer;
    }
}

오답 코드 : 누가 보아도 길다는 것을 알 수 있다.

 

())(() 라는 반례를 풀 수가 없었음 -> '(' 와 ')' 의 개수로만 접근 했기 때문. 열고 닫음의 개수를 확인!
개수를 합하는 도중 sum 음수가 된다면? -> 바로 false가 나오도록 코딩!
class Solution {
    boolean solution(String s) {
        boolean answer = true;
        int n = s.length();
        int sum = 0;
        for(int i=0;i<n;i++){        
            if(sum >= 0 ){
                if(s.charAt(i) == '('){
                    sum += 1;
                }else if(s.charAt(i) == ')'){
                    sum -= 1;
                }
             answer = false;
            }
        }
        if(sum == 0){
            answer = true;  // ())(() 반례 확인 필요
        }
        else if(sum > 0 || sum < 0){
            answer = false;
        }
        
        return answer;
    }
}

 

으어어ㅓㅓㅓ 성공!!!!!!!!!!!!!!! if 문으로 sum>0이라는 조건을 주면, 중간에 ')'가 더 많이 나오는 경우를 방지 할 수 있었다!!!!!!

 


9.

어떤 숫자 n이 주어지면 그 수의 제곱근이 있을 경우, 제곱근값+1의 제곱값을 return, 제곱근이 없으면 -1을 리턴한다.

class Solution {
    public long solution(long n) {
        long answer = 0;
        for(long i=0; i<=n; i++){
            if(i == Math.sqrt(n)){
                answer = (i+1)*(i+1);
                break;
            }else{
                answer = -1;
            }
        }
        return answer;
    }
}
오답의 원인 : for 속의 범위가 기존에는 1부터 n-1까지 였다.
이것이 1이 주어졌을 때를 포함하지 않아 오답이였다. (while로 시도했을 때는 if 문으로 n==1인 경우를 주긴했었다.)

또한 제곱근을 찾는 과정에서 i ==n/i 로 진행하였지만, int의 특성상, 소수부분을 버리기 때문에, int i =0;으로 선언해준 부분을 long i=0;으로 변경하여 연산 시켜 답을 얻게 되었다.

 


10.

주어진 정수를 내림차순으로 변경하여라

ex 118273 -> 873211

 

import java.util.*;

class Solution {
    public long solution(long n) {
        long answer = 0;
        int a = 0;
        int length = ((int) Math.log10(n)+1);
        int[] arr= {};
        arr = new int[length];
        
        for(int i=0; i<length; i++){
            a = (int)(n%10);
            n/=10;
            arr[i] = a;
        }
        Integer[] arr1 = Arrays.stream(arr).boxed().toArray(Integer[]::new);
        Arrays.sort(arr1, Collections.reverseOrder());
        for(int i=0; i<length; i++){
            answer += Math.pow(10, (length-1-i)) * arr1[i];
        }
        //Math.pow(밑, 지수)
        return answer;
    }
}
각 자리수를 나머지로 뽑아 정수 배열을 만들때, Integer[] arr1 = Arrays.stream(arr).boxed().toArray(Integer[]::new);
이부분을 쓰지 않았다. -> 사실 방법도 몰랐다. 이 부분 -> Array 부분을 좀더 공부해야할 필요성 20000%

어쨌든, 각자리수 값을 나머지로 뽑고, sort 내림차순 해준다음, 자릿수만큼 곱해 더해주었다.
그래서 해결완료! 

 

 


11.

두 정수가 주어질 때, 두 정수와 그 사이 값의 합을 구하여라

class Solution {
    public long solution(int a, int b) {
        long answer = 0;
        long sum = 0;
        if(a < b){
            for(int i =a;i<=b;i++){
                sum +=i;
            }
        }else if(a==b){
            sum = a;
        }else if(a > b){
            for(int i =b; i<=a;i++){
                sum +=i;
            }
        }
        answer = sum;
        return answer;
    }
}
sum 을 int로 설정시 오답 -> long  으로 설정 시 정답
이유는?

12.

 

1937년 Collatz란 사람에 의해 제기된 이 추측은, 주어진 수가 1이 될 때까지 다음 작업을 반복하면, 모든 수를 1로 만들 수 있다는 추측입니다. 작업은 다음과 같습니다.

1-1. 입력된 수가 짝수라면 2로 나눕니다. 
1-2. 입력된 수가 홀수라면 3을 곱하고 1을 더합니다. 
2. 결과로 나온 수에 같은 작업을 1이 될 때까지 반복합니다. 

예를 들어, 주어진 수가 6이라면 6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1 이 되어 총 8번 만에 1이 됩니다. 위 작업을 몇 번이나 반복해야 하는지 반환하는 함수, solution을 완성해 주세요. 단, 주어진 수가 1인 경우에는 0을, 작업을 500번 반복할 때까지 1이 되지 않는다면 –1을 반환해 주세요.

class Solution {
    public int solution(long num) {
        int answer = 0;
        int sum = 0;
        int over = -1;
        while(num != 1 && sum <= 500){
            if(sum == 500){
                sum = -1;
                break;
            }
            num = num % 2 == 0 ? num / 2 : num * 3 + 1;
            sum ++;
        }
        answer = sum;
        
        if (num == 1){
            answer = sum;
        }if (sum >= 500){
            sum = over;
        }
        return answer;
    }
}
int num이 아니라 long num을 해야 문제가 풀린다..
그 이유는? long 과 int의 연산시의 차이를 알아야 하는데,,, 추가 공부! 가즈아!

13.

문제 설명

String형 배열 seoul의 element중 "Kim"의 위치 x를 찾아, "김서방은 x에 있다"는 String을 반환하는 함수, solution을 완성하세요. seoul에 "Kim"은 오직 한 번만 나타나며 잘못된 값이 입력되는 경우는 없습니다.

제한 사항
  • seoul은 길이 1 이상, 1000 이하인 배열입니다.
  • seoul의 원소는 길이 1 이상, 20 이하인 문자열입니다.
  • "Kim"은 반드시 seoul 안에 포함되어 있습니다.
class Solution {
    public String solution(String[] seoul) {
        String answer = "";
        int len = seoul.length;
        int index = 0;
        for(int i=0; i < seoul.length;i++){
            if(seoul[i].equals("Kim")){
                index = i;
            }
        }
        
        answer = answer+"김서방은 " + index + "에 있다";
        
        return answer;
    }
}
seoul[i] == "Kim" 을 하였을 때는 오류가 나왔다.
이를 seoul[i].equals("Kim") 으로 바꿨더니 오류가 풀리게 되었다.

14. 

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

 

시도한 알고리즘
-> 최소값을 찾고, 그 인덱스를 구하여 그 인덱스만 제외한 값의 arr[i]를 answer에 대입하려 하였음

실패 요인 -> for 문 하나로, 두 개의 인덱스가 달라야하는 배열을 처리해본 경험이 없었다

+

지식 부족. 특정 인덱스를 어떻게 넣지 않을지? 고민만 하다 실패 -> java.util.Arrays 를 활용하려고 하였으나 실패했음.

 

 

  • 다른 사람의 풀이 : 
import java.util.Arrays;
import java.util.stream.Stream;
import java.util.List;
import java.util.ArrayList;

class Solution {
  public int[] solution(int[] arr) {
      if (arr.length <= 1) return new int[]{ -1 };
      int min = Arrays.stream(arr).min().getAsInt();
      return Arrays.stream(arr).filter(i -> i != min).toArray();
  }
}

여기까지 가는건..? 아직 너무 멀다

이해는 됨. 길이 자체가 1 이하이면, 무조건 -1 을 리턴

아닌 경우, Arrays.stream(arr)의 .min() 최소 값을 .getAsInt() 라는 함수로 찾음

return 구절은, filter를 이용해서 arr에서 min과 같지 않은 경우에만 배열에 넣어 리턴시킴.

 

 

  • 내 답 :
class Solution {
    public int[] solution(int[] arr) {
    int[] answer = {};
    if(arr.length==1){
        answer = new int[1];
        answer[0] = -1;
    }else{
        answer = new int[arr.length-1];
        int min = arr[0];
            
        for(int i=0; i<arr.length; i++){
            min = Math.min(min, arr[i]);
        }
        int index = 0;
        for(int i=0; i<arr.length; i++){
            if(min == arr[i]){
                continue; // 특정 인덱스의 값을 넣지 않는 방법
            }
            answer[index] = arr[i];
            index++; // for 문 하나로, 두 인덱스값이 다른 배열 처리
            }
        }
        return answer;
    }
}

자바,, 진짜 어렵다..

 


문자열을 받아서 내림차순으로 만드는 코드

import java.util.Arrays;
import java.util.Collections;
class Solution {
    public String solution(String s) {
        String answer = "";
        
        String[] str = s.split("");
        Arrays.sort(str, Collections.reverseOrder());
        for(int i=0; i<str.length; i++){
            answer += str[i];
        }
        return answer;
    }
}

받은 문자열을 str이라는 문자 배열에 split으로 저장하여, Arrays의 sort와 Collections 의 reverseOrder()를 이용해서 내림차순 정렬 후, answer에 대입해 주었다.

 

import 없이 하는 방법은? ??

 

다른사람의 풀이

import java.util.Arrays;

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

대단 합니다..

 


15. 카카오 문제

비밀지도

네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.

  1. 지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 "공백"(" ") 또는 "벽"("#") 두 종류로 이루어져 있다.
  2. 전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 "지도 1"과 "지도 2"라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.
  3. "지도 1"과 "지도 2"는 각각 정수 배열로 암호화되어 있다.
  4. 암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.

네오가 프로도의 비상금을 손에 넣을 수 있도록, 비밀지도의 암호를 해독하는 작업을 도와줄 프로그램을 작성하라.

 

 

class Solution {
    public String[] solution(int n, int[] arr1, int[] arr2) {
        String[] answer = {};
        answer = new String[n];
        String[] ar1 = {}; 
        ar1 = new String[n];
        String[] ar2 = {};
        ar2 = new String[n];
        
        
        for(int j = 0; j<n; j++){
            int c = arr1[j];
            String a = "";
            for(int i = n; i > 0; i--){
                int b = (int) Math.pow(2,i-1);
                if(c < b){
                    a += " ";
                    
                }else if(c >= b){
                    a += "#";
                    c -= b;
                }
            }ar1[j] = a;
            
        }
        //arr2
        for(int j = 0; j<n; j++){
            int c = arr2[j];
            String a = "";
            for(int i = n; i > 0; i--){
                int b = (int) Math.pow(2,i-1);
                if(c < b){
                    a += " ";
                    
                }else if(c >= b){
                    a += "#";
                    c -= b;
                }
            }ar2[j] = a;  
        }
        // arr1, 2를 비교해 answer 추출
        for(int k=0; k<n; k++){
            String abc = "";
            for (int l=0; l<n; l++){
                if(ar1[k].charAt(l) == '#' || ar2[k].charAt(l) == '#'){
                    abc += "#";
                }else{
                    abc += " ";
                }
            }answer[k] = abc;
        }

        
        
        return answer;
    }
}

사실 더 간단히 해야하는데,,, 2진법으로 바꾸는 법을 노가다로 풀었따...

 

다른 사람의 풀이를 확인해 보자!

 

  class Solution {
    public String[] solution(int n, int[] arr1, int[] arr2) {
        String[] answer = new String[n];       
        for(int i = 0; i < n; i++) {
            String bi = Integer.toBinaryString(arr1[i] | arr2[i]);
            bi = "0".repeat(n - bi.length()) + bi;
            answer[i] = bi.replaceAll("1", "#").replaceAll("0", " ");
        }
        return answer;
    }
}

사실 이 문제의 핵심은 비트연산이다.

Integer.toBinaryString을 알고 있다면 쉽게 풀렸을 터..

반응형
LIST

'개인 프로젝트 > JAVA 학습' 카테고리의 다른 글

함수 기록기  (0) 2023.08.18
Java 객체지향 개념  (2) 2023.08.16
Java 기본문법 2  (0) 2023.08.08
JAVA 프로그래밍  (0) 2023.08.03