입출력 예
|my_str|n|result|
|:----:|:-:|:--:|씩 잘라서 저장한 배열을 return하도록 solution 함수를 완성해주세요.
|"abc1Addfggg4556b"|6|["abc1Ad", "dfggg4", "556b"]|
|"abcdef123"|3| ["abc", "def", "123"]|
입출력 예 설명
유의사항
나의 풀이
package 프로그래머스;
public class CutArray {
public static String[] solution(String my_str, int n) {
String[] answer ;
int length = my_str.length();
if(my_str.length() % n == 0) {
answer = new String[my_str.length()/n];
}else {
answer = new String[(my_str.length()/n) + 1 ];
}
for(int i = 0; i < answer.length; i++) {
if(length - n < 0) {
answer[i] = my_str.substring(n*i, my_str.length());
}else {
answer[i] = my_str.substring(n*i, n*(i+1));
length -=n;
}
}
return answer;
}
public static void main(String[] args) {
solution("abcdef123",3);
}
}
나의 생각
my_str.length()
를 n
으로 나눈 나머지가 0인 것과, 아닌것으로 String[] 배열의 크기를 지정해주는데, 나머지가 0
이라는 것은 배열의 길이가 똑같은 크기로 딱 맞게 떨어짐을 의미한다(나누어 떨어지지 않는 경우 마지막에 추가로 한개의 배열 요소를 추가). 그리고 for문을 통해, answer
배열에 String의 substring
메서드를 사용하여 시작 index와 끝 index로 원래의 배열을 짜른는 방법을 사용하였다. if(length - n < 0)
는 배열의 크기가 다른 Index가 존재하면 이는 마지막 배열 요소에 남은 문자열 전체를 저장한다는 의미가 된다. else
문에서는 answer 배열에 my_str
의 문자열을 일정한 크기로 자른뒤, length
의 길이를 for문에서 n
만큼 빼 결국 남은length
는 일정한 크기로 자르고 남은 부분을 담는다는 의미이다.
이번 문제는 머릿속으로 생각한 부분을 그대로 코드로 구현하였다는 점에서 한 단계 앞으로 나아갔다는 기분이 들었다. 앞으로는 코드에서 불필요한 부분까지 한 걸음더 생각하여 문제해결 할 수 있도록 해야겠다.
제한사항
+
,-
만 존재합니다.입출력 예
my_string | result |
---|---|
"3 + 4" | 7 |
입출력 예 설명
나의 생각
첫번째 방법 (잘못생각한 풀이)
package 프로그래머스;
public class StringCal {
public static int solution(String my_string) {
int answer = 0;
for(int i = 0; i < my_string.length(); i++) {
char ch = my_string.charAt(i);
if(Character.isDigit(ch)) {
answer = (int)ch-(int)'0'; // answer = 3
System.out.println(answer);
}else if(ch == '+') { // '+' = 42
answer += (int)ch-(int)'0';
System.out.println(answer);
}else if(ch == '-') { // '-' = 45
answer -= (int)ch-(int)'0';
System.out.println(answer);
}
}
return answer;
}
public static void main(String[] args) {
solution("3 + 4 - 6");
}
}
Character
클래스의 메서드를 사용해서 숫자를 판별하고,+
,-
를 판별해서 덧셈과 뺄셈 연산을 처리하면 되지않을까 라고 생각을 하고 문제에 접근...
두번째 방법 (정답)
package 프로그래머스;
public class StringCal {
public static int solution(String my_string) {
int answer = 0;
String[] str = my_string.split(" ");
answer += Integer.parseInt(str[0]);
for(int i = 1; i < str.length -1 ; i++) {
if(str[i].equals("+")) {
answer += Integer.parseInt(str[i+1]);
}
if(str[i].equals("-")) {
answer -= Integer.parseInt(str[i+1]);
}
}
return answer;
}
public static void main(String[] args) {
solution("3 - 4 - 6");
}
}
나의 생각
먼저, my_string 문자열을 String[] 배열에 담는데, 공백없이 배열에 담기 위해 " "
를 사용하였다. answer += Integer.parseInt(str[0])
는 answer에 my_string문자열의 첫글자를 더하여 for문의 특정 조건 ( "+"
, "-"
) 일때 검출된 문자를 int형으로 변환하여 더하거나 빼주기 위한 로직이다. str.length - 1
의 조건 역시, 전체 배열 크기만큼 반복을 돌려도 상관 없으나, 전체 배열의 마지막 배열index에는 숫자가 반드시 들어 있기때문에, str.length-1
을 하여 연산자(+,-)
까지만 반복을 돌린다는 의미이다.
입출력 예
balls | share | result |
---|---|---|
3 | 2 | 3 |
5 | 3 | 10 |
입출력 예 설명
hint
나의 풀이
오답( 테스트 클래스 오답)
package programmers;
public class NumberOfCases {
public static long solution(int balls, int share) {
long n = 1;
long m = 1;
for(int i = balls; i > balls - share; i--) {
n*=i;
}
for(int j =share; j > 0; j--) {
m*=j;
}
return n/m;
}
public static void main(String[] args) {
solution(5,2);
}
}
BigInteger (정답)
package programmers;
import java.math.BigInteger;
public class NumberOfCases {
public static BigInteger solution(int balls, int share) {
BigInteger numerator = BigInteger.ONE;
BigInteger denominator = BigInteger.ONE;
for (int i = balls; i > balls - share; i--) {
numerator = numerator.multiply(BigInteger.valueOf(i));
}
for (int i = share; i > 0; i--) {
denominator = denominator.multiply(BigInteger.valueOf(i));
}
System.out.println(numerator.divide(denominator));
return numerator.divide(denominator);
}
public static void main(String[] args) {
solution(5,2);
}
}
나의 풀이
문제에서 힌트까지 준거보면 문제를 막연히 풀기보단,
overflow
를 어떻게 해결할 것인가를 중점적으로 해결해야 하는거같다. 나는 java의BigInteger
클래스를 활용하여 문제를 풀었지만, 문제의 의도는 점차 늘어나는 자리수의 문제를 overflow 없이 어떻게 해결 할 것인가? 를 생각해보라는 의미였던거 같다.
재귀적 풀이 (recursive)
class Solution {
public int solution(int balls, int share) {
int answer = 0;
if(balls == share || share == 0)
answer = 1;
else{
answer = solution(balls - 1, share - 1) + solution(balls - 1, share);
}
return answer;
}
}
- 입력 : 두 정수 balls와 share
- 출력 : balls개의 공을 share 명의 사람에게 나누어주는 방법의 수
- 이 함수는 다음과 같은
점화식
을 사용하여 문제를 해결합니다.
- 기저 조건(base case) : 만약 balls와 share가 같거나 share가 0이면, 리턴은 1입니다. 이것은 모든 공을 동일한 수로 나눌 수 있거나 공을 나눌 필요가 없는 경우를 의미
- 재귀적 접근(recursive approach) : 그렇지 않으면, 함수는 다음 두 가지 경우의 합을 반환
balls - 1
개의 공을share - 1
명의 사람들에게 나누어주는 방법의 수 : 이 경우는 각 사람들이 최소한 하나의 공을 가지고 있는 경우를 의미함balls - 1
개의 공을share
명의 사람들에게 나누어주는 방법의 수 : 이 경우 적어도 한 사람이 공을 받지 않는 경우를 의미함
입출력 예
sides | result |
---|---|
[1,2] | 1 |
[3,6] | 5 |
[11,7] | 13 |
입출력 예 설명
입출력 예 #1
입출력 예 #2
입출력 예 #3
나의 풀이
package programmers;
public class TriangleCompletion {
public static int solution(int[] sides) {
int max = Math.max(sides[0], sides[1]);
int min = Math.min(sides[0], sides[1]);
int cnt = 0;
for(int i = (max - min) ; i < max; i++) {
cnt++;
}
for(int i = max+1; i < max+min; i++) {
cnt++;
}
return cnt;
}
public static void main(String[] args) {
solution(new int[] {3,6});
}
}
나의 생각
입출력 예 #3
의 설명을 바탕으로 로직을 구성해 보았다.
- 가장 긴 변이 11인 경우
- 될 수 있는 나머지 한 변은 5, 6, 7, 8, 9, 10, 11 로 7개입니다.
- 나머지 한 변이 가장 긴 변인 경우
- 될 수 있는 한 변은 12, 13, 14, 15, 16, 17 로 6개입니다.
- 따라서 7 + 6 = 13을 return합니다.
매개변수로 두 변수가 주어졌을때, 두 수 중에 큰 수와 작은 수를 판별을 먼저 해야하기 때문에
Math
클래스의 max
,min
메서드를 활용하여 max, min 값을 판별하였다. 그리고 가장 긴 별이 max 일 경우와 나머지 한 변의 길이가 가장 긴 경우로 나누어 for문을 돌려 마지막으로 cnt(카운트)를 리턴하였다. 문제 해결을 아주 직관적으로 풀었는데, 이를 좀 더 클린하게 표현하면 다음과 같다.
int max = Math.max(sides[0], sides[1]);
int min = Math.min(sides[0], sides[1]);
java의 내부 클래스와 메서드를 활용하는 방법도 좋은 방법이지만 때로는 원리적으로 문제를 풀 줄도 알아야 하기에 Math
클래스 대신 아래와 같은 방법도 사용할 수 있다.
int max = sides[0] > sides[1] ? sides[0] : sides[1]
int min = sides[0] > sides[1] ? sides[1] : sides[0]
삼항 연산자
를 활용하여 max
값과 , min
값을 구할 수 있다. 그리고 아래의 for문 두 개를 보면 공통점을 발견할 수 있다.
두 조건을 더해보자
int i = max - min + max +1; i < max + max + min
int i = 2max - min + 1; i < 2max + min (i에 2max - min + 1을 대입)
2max - min + 1 < 2max + min
따라서, 나머지 한 변이 될 수 있는 정수의 개수를 이항 정리를 하면2 * min - 1
가 성립된다. 위 조건을 바탕으로 코드를 재구성하면 아래와 같다.
package programmers;
public class TriangleCompletion {
public static int solution(int[] sides) {
int max = sides[0] > sides[1] ? sides[0] : sides[1];
int min = sides[0] > sides[1] ? sides[1] : sides[0];
return 2 * min - 1;
}
public static void main(String[] args) {
solution(new int[] {11,7});
}
}
제한사항
입출력 예
spell | dic | result |
---|---|---|
["p", "o", "s"] | ["sod", "eocd", "qixm", "adio", "soo"] | 2 |
["z", "d", "x"] | ["def", "dww", "dzx", "loveaw"] | 1 |
["s", "o", "m", "d"] | ["moos", "dzx", "smm", "sunmmo", "som"] | 2 |
입출력 예 설명
유의사항
나의 풀이
package programmers;
public class AlienDictionary {
public static int solution(String[] spell, String[] dic) {
int answer = 0;
String[] word = new String[dic.length];
int spellLength = 0;
for (String s :spell) {
spellLength += s.length();
}
for(int i = 0; i < dic.length; i++) {
word[i] = dic[i];
for(String s : spell) {
word[i] = word[i].replaceFirst(s, "");
}
if(spellLength == dic[i].length() && word[i].length() == 0) {
answer = 1;
break;
}else {
answer = 2;
}
}
System.out.println(answer);
return answer;
}
public static void main(String[] args) {
String[] spell = {"p", "o", "s"};
String[] dic = {"sod", "eocd", "qixm", "adio", "soo"};
solution(spell, dic);
}
}
나의 생각
String 배열 dic의 원소 sod
,eocd
,qixm
,adio
,soo
중에 spell의 모든 단어를 포함하는 문자가 있으면 return 1
, 아니면 return 2
를 하는 문제이다. for문을 dic.length
만큼 반복을 돌려, dic의 원소를 word
에 그대로 복사한다. 향상된 for문을 돌려 word[i] = word[i].replaceFirst(s, "")
에 의해 word에 spell의 문자가 포함되면, word의 문자는 빈문자로 치환한다. 예를들어, word = "soo"
라고 할 때, spell의 "s","o"
문자를 포함하는데, replaceFirst
메서드를 통해 두개의 o
중 하나만 치환되므로, " o"
만 남게된다. 문제에서 spell의 모든 문자가 dic의 원소에 포함되야 하므로 최종적으로 해당 식을 만족해야 문제가 성립된다.
if(spellLength == dic[i].length() && word[i].length() == 0) {
answer = 1;
break;
}else {
answer = 2;
}
spell 의 원소의 크기는 모두 1
이고, 해당 식을 이용하여 spell의 전체 길이를 구할 수 있다.
for (String s :spell) {
spellLength += s.length();
}
따라서, spell원소의 전체 길이와 dic[index].length() 의 길이가 같아야, spell의 원소를 다 포함한다고 할 수 있다. 그리고 &&
조건으로 복사된 word[i] 의 원소 " "
의 길이가 0이 되야 word[i]의 원소가 모든 spell의 문자를 포함했기때문에 빈문자열로 존재하게 된다.
다른 방법
import java.util.*;
class Solution {
public int solution(String[] spell, String[] dic) {
Arrays.sort(spell);
for (String d : dic) {
String[] dSplit = d.split("");
Arrays.sort(dSplit);
if (Arrays.equals(dSplit, spell)) {
return 1;
}
}
return 2;
}
}
풀이법
spell = ["z","d","x"] , dic = ["def","dww","dzx","loveaw"]
일때,
Array.sort(spell)
정렬을 통해 spell = ["d","x","z"] 가 된다.dic
배열을 반복문을 실행하여,String[] dSplit = d.split("")
를 통해 현재단어 "def"를 문자 단위로 쪼개어dSplit
배열에 저장한다.Arrays.sort(dSplit)
를 통해 배열을 정렬하여 dSplit = ["d","e","f"]가 된다.if(Arrays.equals(dSplit,spell){
정렬된dSplit
,spell
배열을 비교한다.- 세번째 단어
["d","x","z"]
와 spell의["d","x","z"]
배열의 비교하여 같으므로return 1
이 반환되며, 함수가 종료된다.