Programmers #12

이강용·2023년 4월 19일
0

Programmers

목록 보기
12/58

이진수 더하기

📑 문1) 이진수를 의미하는 두 개의 문자열 bin1과 bin2가 매개변수로 주어질 때, 두 이진수의 합을 return하도록 solution 함수를 완성해주세요.


입출력 예

bin1bin2result
"10""11""101"
"1001""1111""11000"

입출력 예 설명

  • 10 + 11 = 101 이므로 "101" 을 return합니다.
  • 1001 + 1111 = 11000 이므로 "11000"을 return합니다.

나의 풀이

package 프로그래머스;

public class BinaryNumber {
	public static String solution(String bin1, String bin2) {
        String  answer = "";
		int num1 = Integer.parseInt(bin1, 2);
		int num2 = Integer.parseInt(bin2, 2);
		
        int binary = num1 + num2;
        
        answer = Integer.toBinaryString(binary);
        return answer;
    }
	
	public static void main(String[] args) {
		solution("10","11");
	}

}

나의 생각

처음에는 String answer 변수에 빈 문자열을 할당, 그리고 Integer.parseInt() 메서드를 사용하여 두 이진수 문자열을 각각 10진수로 변환후 , num1,num2 변수에 저장, 이후 num1,num2를 더한 값을 binary 변수에 저장

마지막으로 Integer.toBinaryString() 메서드를 사용하여 binary 변수에 저장된 값을 다시 이진수 문자열로 변환하여 answer 변수에 할당하고, answer 변수를 리턴


해결 중인 풀이법

package 프로그래머스;

import java.util.Arrays;

public class BinaryNumber {
	public static String solution(String bin1, String bin2) {
        StringBuilder binary = new StringBuilder();
      
        String[] b1Split = bin1.split("");
        String[] b2Split = bin2.split("");
        System.out.println(Arrays.toString(b1Split));
        System.out.println(Arrays.toString(b2Split));
        
        for(int i = 0; i < b1Split.length; i ++) {
        	if(b1Split[i].equals("0") && b2Split[i].equals("0") ) {
        		binary.append("0");
        	}else if(b1Split[i].equals("0") && b2Split[i].equals("1")||b1Split[i].equals("1") && b2Split[i].equals("0")) {
        		binary.append("1");
        	}else {
        		binary.append("10");
            }
        }
        
        
        System.out.println("binary: "+ binary);
        
        String answer ="";
        
        return answer;
    }
	
	public static void main(String[] args) {
		solution("1001","1111");
	}

}

컨트롤 제트

📑 문2) 숫자와 "Z"가 공백으로 구분되어 담긴 문자열이 주어집니다. 문자열에 있는 숫자를 차례대로 더하려고 합니다. 이 때 "Z"가 나오면 바로 전에 더했던 숫자를 뺀다는 뜻입니다. 숫자와 "Z"로 이루어진 문자열 s가 주어질 때, 머쓱이가 구한 값을 return 하도록 solution 함수를 완성해보세요.


제한사항

  • 1 ≤ s의 길이 ≤ 200
  • -1,000 < s의 원소 중 숫자 < 1,000
  • s는 숫자, "Z", 공백으로 이루어져 있습니다.
  • s에 있는 숫자와 "Z"는 서로 공백으로 구분됩니다.
  • 연속된 공백은 주어지지 않습니다.
  • 0을 제외하고는 0으로 시작하는 숫자는 없습니다.
  • s는 "Z"로 시작하지 않습니다.
  • s의 시작과 끝에는 공백이 없습니다.
  • "Z"가 연속해서 나오는 경우는 없습니다.

입출력 예

sresult
"1 2 Z 3"4
"10 20 30 40"100
"10 Z 20 Z 1"1
"10 Z 20 Z"0
"-1 -2 -3 Z"-3

입출력 예 설명

  • 1+2-2+3 = 4
  • 10+20+30+40 = 100
  • 10-10+20-20+1 = 1
  • 10-10+20-20 = 0
  • -1-2-3+3 = -3

나의 풀이

package programmers;

public class CtrlZ {
	public static int solution(String s) {
        int answer = 0;
        String[] str = s.split(" ");

        
        for(int i = 0; i < str.length; i++) {
        	System.out.println(str[i]);
            if("Z".equals(str[i])) {
        		answer -= Integer.parseInt(str[i-1]);
            	
            }else {
            	answer += Integer.parseInt(str[i]);
            }
        }
      
        return answer;
    }
	
	public static void main(String[] args) {
		solution("-1 -2 -3 Z");
	}

}

나의 생각

매개변수 String s = "-1 -2 -3 Z" 가 들어 있을때, String 배열 str에 매개변수 s를 띄어쓰기 " "로 짤라, 배열에 한칸씩 넣는다.

먼저, for문을 돌려 전체 반복을 시행하고, Z문자가 나오기 전까지, Integer.parseInt메서드를 사용하여 문자를 int형으로 변환하여 answer에 더해준다. 만약, str[i] 값에 Z 가 포함되면,answer -= Integer.parseInt(str[i-1]); 하여 Z Index 직전의 값을 answer에서 빼주고 return.


Stack을 적용한 풀이 법

import java.util.Stack;

public class CtrlZ {
    public static int solution(String s) {
        int answer = 0;
        Stack<Integer> stack = new Stack<>();
        String[] str = s.split(" ");
        
        for (int i = 0; i < str.length; i++) {
            if ("Z".equals(str[i])) {
                if (!stack.isEmpty()) {
                    answer -= stack.pop();
                }
            } else {
                int num = Integer.parseInt(str[i]);
                stack.push(num);
                answer += num;
            }
        }
        
        return answer;
    }
}

Stack 이란

  • Java에서 제공하는 스택(Stack)자료구조의 인스턴스를 선언하는 코드
  • 스택은 Last In, First Out (LIFO)원칙을 따르는 자료구조로, 가장 나중에 들어온 요소가 가장 먼저 나가는 순서를 따름

예시 👉🏻 Stack<Integer>

  • push(E item) : 스택의 맨 위에 요소를 추가
  • pop() : 스택의 맨 위에 있는 요소를 제거하고 반환, 스택이 비어있으면 EmptyStackException이 발생
  • peek() : 스택의 맨 위 에 있는 요소를 제거하지 않고 반환
  • isEmpty() : 스택이 비어있는지 확인, 비어있으면 true , 그렇지않으면 false를 반환
  • size() : 스택에 있는 요소의 개수를 반환

스택은 다양한 알고리즘과 문제 해결에 사용되며, 괄홍 쌍 검사, 후위 표기법, DFS (깊이 우선 탐색)등의 알고리즘에서 자주 사용됨


소인수분해

📑 문2) 소인수분해란 어떤 수를 소수들의 곱으로 표현하는 것입니다. 예를 들어 12를 소인수 분해하면 2 2 3 으로 나타낼 수 있습니다. 따라서 12의 소인수는 2와 3입니다. 자연수 n이 매개변수로 주어질 때 n의 소인수를 오름차순으로 담은 배열을 return하도록 solution 함수를 완성해주세요.


입출력 예

nresult
12[2,3]
17[17]
420[2,3,5,7]

입출력 예 설명

  • 12를 소인수분해하면 2 2 3 입니다. 따라서 [2, 3]을 return합니다.

  • 17은 소수입니다. 따라서 [17]을 return 해야 합니다.

  • 420을 소인수분해하면 2 2 3 5 7 입니다. 따라서 [2, 3, 5, 7]을 return합니다.


나의 풀이

package programmers;

import java.util.LinkedHashSet;
import java.util.Set;

public class Factorization {
    public static Set<Integer> solution(int n) {
        Set<Integer> answer = new LinkedHashSet<>();
       
        	for(int i = 2; i <= n; i++) {
        		while(n%i == 0 ) {
        			n /= i;
        			answer.add(i);
        		}
        	}
        return answer;
    }

    public static void main(String[] args) {
       
    solution(990);
            
        
    }
}

나의 생각

예를들어, n = 990 일때, 990의 소인수 분해 값은 233511 이 된다. 문제에선 소인수 값을 중복없이 추출하라 했으므로, 추출된 값을 List나 다른 자료형 구조에 담지말고 Set 자료형을 써야겠다고 생각했다. 소인수분해시 , 반복문을 int i = 1부터 시행할 필요가 없기때문에, int i = 2 부터, 매개변수 n까지 반복을 돌린다고 하지만, 실제론 반복문의 n값이 점차 줄어들기때문에, 반복문의 반복 횟수도 점차 줄어든다.

따라서, n % i == 0 을 무한 반복 돌려, n % i 즉, 나머지가 0이 될때까지, n의 값을 Set주머니에 담아 반복을 제거하여 answer값을 리턴한다.


내가 처음 생각했던 풀이 ( 반례 있음, 정답 아님 )

package programmers;

import java.util.LinkedHashSet;
import java.util.Set;

public class Factorization {
    public static Set<Integer> solution(int n) {
        Set<Integer> answer = new LinkedHashSet<>();
       
        	for(int i = 2; i <= n; i++) {
        		if(n%i == 0 ) {
        			n /= i;
        			answer.add(i);
                    i = 2;
        		}
        	}
       System.out.println(answer);
        return answer;
    }

    public static void main(String[] args) {
       
    solution(990);
            
        
    }
}

나의 생각

내가 처음에 했던 풀이법이다. While문 대신, if문을 썼는데, 반례 25개 중에 2개가 걸리는 바람에 문제를 다시 풀었다.

if문 풀이 (반례가 존재함)while문 풀이

i = 1로 초기화 시켰을 때 (정답)


import java.util.LinkedHashSet;
import java.util.Set;
class Solution {

    public static Set<Integer> solution(int n) {
        Set<Integer> answer = new LinkedHashSet<>();
       
        	for(int i = 2; i <= n; i++) {
        		if(n%i == 0 ) {
        			n /= i;
        			answer.add(i);
                    i = 1;
        		}
        	}
     
        return answer;
    }
}

왜 i = 1, i = 2 로 초기화 시켰을 때 결과가 다를까 ?

  • 한참 고민하다 그 이유를 알았다... 나는 반복의 시작이 i = 2니까, 마지막 초기화를 i = 2로 해줬는데, 다음반복에서 i = 2부터 시작하는것이 아니라 2 -> 3으로 점프해서 i = 3부터 시작하기 때문에 반례가 존재했던 것! 따라서, i = 1로 초기화 하면, 다음 반복에서 i = 2로 시작하기 때문에 확인한 소수를 다시 확인하게 되어 누락된 소인수를 찾을 수 있음

  • i = 2로 초기화 했을 때i = 1로 초기화 했을 때

공 던지기

📑 문3) 머쓱이는 친구들과 동그랗게 서서 공 던지기 게임을 하고 있습니다. 공은 1번부터 던지며 오른쪽으로 한 명을 건너뛰고 그다음 사람에게만 던질 수 있습니다. 친구들의 번호가 들어있는 정수 배열 numbers와 정수 K가 주어질 때, k번째로 공을 던지는 사람의 번호는 무엇인지 return 하도록 solution 함수를 완성해보세요.


제한 사항

  • 2 < numbers의 길이 < 100
  • 0 < k < 1,000
  • numbers의 첫 번째와 마지막 번호는 실제로 바로 옆에 있습니다.
  • numbers는 1부터 시작하며 번호는 순서대로 올라갑니다.

입출력 예

numbersKresult
[1, 2, 3, 4]23
[1, 2, 3, 4, 5, 6]53
[1, 2, 3]32

입출력 예 설명

입출력 예 설명 #1

  • 1번은 첫 번째로 3번에게 공을 던집니다.
  • 3번은 두 번째로 1번에게 공을 던집니다.

입출력 예 설명 #2

  • 1번은 첫 번째로 3번에게 공을 던집니다.
  • 3번은 두 번째로 5번에게 공을 던집니다.
  • 5번은 세 번째로 1번에게 공을 던집니다.
  • 1번은 네 번째로 3번에게 공을 던집니다.
  • 3번은 다섯 번째로 5번에게 공을 던집니다.

나의 풀이

package programmers;

public class TossBall {
	public static int solution(int[] numbers, int k) {
        int answer = 0;
        for(int i = 0; i < k; i++) {
        	System.out.println(i+1 + "회 시행 : " + numbers[(2*i)%numbers.length] + " -> " + numbers[((2*i)+2)%numbers.length]);
        	answer = numbers[(2*i)%numbers.length];
        }
        
        System.out.println("최종 return 값: " + answer);
        return answer;
    }
	
	public static void main(String[] args) {
		int[] numbers = {1, 2, 3, 4, 5, 6};
		solution(numbers, 5);
	}

}

나의 생각

요즘 부쩍.. Level 0 단계 이지만, 고민을 하게 만드는 문제가 많은거 같다. 이번 문제 역시
쉽다면 쉽게 풀 수 있었던 문제같은데, 나의 경우 노트를 펴놓고 규칙성을 찾으면서 문제를 풀었다. for문에서의 반복후, for문을 재반복 하기 위해서는 모듈로 연산 을 연산을 하면 쉽게 풀 수 있다. 나는 %계산으로 나머지를 활용하여 반복을 돌렸는데, 이게 모듈로 연산 이라고 한다... 예를 보면 int[] numbers = {1,2,3,4,5,6} 이 있고, 5회 시행때 공을 던지는 사람이 누구인가? 에 대한 답을 찾는 문제였다. 핵심 키워드는 answer = numbers[(2*i)%numbers.length] 로 index는 짝수가 되어야 내가 원하는 값이 도출 되기때문에 위와 같은 규칙을 적용하여 문제를 해결할 수 있었다.

  • i = 0일 때:
    numbers[(2*0)%3] = numbers[0]이므로, 배열에서 첫 번째 요소인 1을 선택
  • i = 1일 때:
    numbers[(2*1)%3] = numbers[2]이므로, 배열에서 세 번째 요소인 3을 선택
  • i = 2일 때:
    numbers[(2*2)%3] = numbers[1]이므로, 배열에서 두 번째 요소인 2을 선택

클린 코드

class Solution {
    public int solution(int[] numbers, int k) {
        return (k-1)*2 % numbers.length+1;
    }
}

7의 개수

📑 문4) 머쓱이는 행운의 숫자 7을 가장 좋아합니다. 정수 배열 array가 매개변수로 주어질 때, 7이 총 몇 개 있는지 return 하도록 solution 함수를 완성해보세요.


입출력 예

arrayresult
[7,77,17]4
[10,29]0

입출력 예 설명

  • [7, 77, 17]에는 7이 4개 있으므로 4를 return 합니다.
  • [10, 29]에는 7이 없으므로 0을 return 합니다.

나의 풀이

package 프로그래머스;

public class NumberOfSeven {
	public static int solution(int[] array) {
		int count = 0;
	    String str = "";
	    for (int num : array) {
	        str += num;
	    }

	    for (int i = 0; i < str.length(); i++) {
	        if (str.charAt(i) == '7') {
	            count++;
	        }
	    }

	    return count;
    }
	
	public static void main(String[] args) {
		
		solution(new int[]{7,77,17});
	}

}


나의 생각

늘 내가 놓쳤던 부분 중에 하나인 정해진 매개변수의 타입을 말 그대로 정해진 대로 보는것이다. 즉, String타입의 변수가 있다고 했을때, 이 변수를 String타입으로만 보고, Int형 타입의 변수를 Int형으로만 문제를 접근하기때문에 더 활용도가 높은 메서드를 사용하지 못하였다. 이 문제 역시 Int형 배열{7,77,17}이 있을때, 여기에 포함된 숫자 7의 갯수가 몇개인가? 를 찾는 문제이다. 단순하게 int형으로만 생각하면 7은 그렇다치고.. 77이나, 17,177,1771 등, 나눠서 나머지를 계산할 것인가? 나는 이 int형 배열을 먼저 문자형으로 변환하여 str변수에 넣어 77717 에서 문자7의 갯수를 찾아 리턴하는 방법을 사용하였다.


영어가 싫어요

📑 문5) 영어가 싫은 머쓱이는 영어로 표기되어있는 숫자를 수로 바꾸려고 합니다. 문자열 numbers가 매개변수로 주어질 때, numbers를 정수로 바꿔 return 하도록 solution 함수를 완성해 주세요.


제한사항

  • numbers는 소문자로만 구성되어 있습니다.
  • numbers는 "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" 들이 공백 없이 조합되어 있습니다.
  • 1 ≤ numbers의 길이 ≤ 50
  • "zero"는 numbers의 맨 앞에 올 수 없습니다.

입출력 예

numbersresult
"onetwothreefourfivesixseveneightnine"123456789
"onefourzerosixseven"14067

입출력 예 설명

  • "onetwothreefourfivesixseveneightnine"를 숫자로 바꾼 123456789를 return합니다.
  • "onefourzerosixseven"를 숫자로 바꾼 14067를 return합니다.

나의 생각

  • 내가 풀었던 첫번째 방법 ( 잘못된 풀이 방법 )
package 프로그래머스;

import java.util.LinkedHashMap;
import java.util.Map;

public class IHateEnglish {
	public static long solution(String numbers) {
		long answer = 0;
		String str = "";
		
        Map<Integer, String> strToInt = new LinkedHashMap<>();
        
        strToInt.put(0,"zero");
        strToInt.put(1,"one");
        strToInt.put(2,"two");
        strToInt.put(3,"three");
        strToInt.put(4,"four");
        strToInt.put(5,"five");
        strToInt.put(6,"six");
        strToInt.put(7,"seven");
        strToInt.put(8,"eight");
        strToInt.put(9,"nine");
        
        
        
        for(Map.Entry<Integer, String> entry : strToInt.entrySet()) {
        	if(numbers.contains(entry.getValue())) {
        		str += entry.getKey();
        	}
        }
        
        System.out.println(str);
        
        answer = Integer.parseInt(str);       
        System.out.println(answer);       
        return answer;
    }
	
	public static void main(String[] args) {
		
		solution("ninesevenzerotwotwo");
	}

}

숫자를 오름차순으로 정렬하며, 중복된 문자를 인식 못하는 문제가 발생
중간에 "zero" 문자가 있다면, 숫자로 변환시 제일 첫자리가 0이 되기때문에 0을 생략하고 숫자가 찍히는 문제가 발생


두번째 방법 ( 정답 )

package 프로그래머스;

import java.util.LinkedHashMap;
import java.util.Map;

public class IHateEnglish {
	public static long solution(String numbers) {
		long answer = 0;
		StringBuilder str = new StringBuilder();
		
        Map<String, Integer> strToInt = new LinkedHashMap<>();
        
        strToInt.put("zero", 0);
        strToInt.put("one", 1);
        strToInt.put("two", 2);
        strToInt.put("three", 3);
        strToInt.put("four", 4);
        strToInt.put("five", 5);
        strToInt.put("six", 6);
        strToInt.put("seven", 7);
        strToInt.put("eight", 8);
        strToInt.put("nine", 9);
        
        
        while(!numbers.isEmpty()) {
        for(Map.Entry<String, Integer> entry : strToInt.entrySet()) {
        	if(numbers.startsWith(entry.getKey())) {
        		
        		str.append(entry.getValue());
        		numbers = numbers.substring(entry.getKey().length());
        		break;
        	}
   		  }
        }
        
        answer = Long.parseLong(str.toString());          
        return answer;
    }
	
	public static void main(String[] args) {
		
		solution("ninesevenzerotwotwo");
	}

}

나의 생각

Map 자료구조에는 keyvalue가 한쌍으로 들어가는데, 이를 이용하면 되겠다라는 생각을 먼저하게됐다. key또는value를 비교하여, key가 일치하면, value 값을 StringBuilder 형 변수 str에 추가하는 방법을 사용하였다. while문의 조건인 ! numbers.isEmpty() 를 통해, 무한 반복시키고, for문을 통해 반복을 돌려, numbers에서 특정문자로 시작하는 문자가 있으면 str.append 및 numbers는 substring을 통해 문자를 빼주고, 문자가 아무것도 없으면 while문을 종료 한다.


획기적인 코드

class Solution {
    public long solution(String numbers) {

            String[] numbers_arr = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

            for (int i = 0; i < numbers_arr.length; i++) {
                numbers = numbers.replaceAll(numbers_arr[i], String.valueOf(i));
            }

            long answer = Long.parseLong(numbers);
            return answer;
        }
}
  • zero ~ nine 까지 String[] 배열에 담는다.
  • String[] 배열의 크기만큼 반복을 돌려
  • 매개변수 String numbers을 zero ~ nine 까지 일치하면 숫자(문자로) replaceAll 해주는 방법으로 문제를 해결

profile
HW + SW = 1

0개의 댓글