문제 : 문자열 "hello"에서 각 문자를 오른쪽으로 이동시킨다. 매개변수가 A,B로 주어질 때 A가 밀어서 B가 될수 있으면, 밀어야 되는 최소 횟수를 반환한다. A가 아무리 밀어도 B가 될 수 없으면 -1을 반환한다.
한글풀이
1. A,B가 일치하면 0을 리턴한다(얼리리턴)
2. A의 가장 오른쪽 문자를 맨 앞으로 붙인다.
3. 2번을 반복하며 B와 일치하는지 찾는다.
4. 일치하면 그 횟수를 반환한다.
5. 불가능하다면 -1을 반환한다.
가장 어려웠던 점은 문자열을 수정하는 작업이었다. 가장 뒤의 문자를 가장 앞으로 붙여와야 하는데, 문자열은 일부 수정이 불가능하므로 배열 메소드(unshift, pop, slice)를 써서 풀어야 한다.
배열 메소드들에 대한 제대로 된 이해가 필요한 문제였다.
function solution(A,B){
//얼리리턴
if(A === B)
return 0;
//A를 배열로 만들기 (디스트럭쳐)
const Aarr = [...A]
//반복문 돌리기 . Aarr의 가장 뒤의 요소를 pop해서
//가장 앞에다 붙이기
for(let i = 0 ; i< A.length; i++){
Aarr.unshift(Aarr.pop())
A = Aarr.join('');
if(A === B) return i+1;
}
//앞에서 안나오면 -1리턴
return -1;
}
배열메소드 unshift와 pop은 원본 배열을 변경한다. 변경된 배열을 반환한고 싶다면 수정된 원본 배열(Aarr)을 받아야지, 변수에 할당하면 안된다.
function solution(A,B){
if(A === B)
return 0; //얼리리턴
//for 반복문을 사용.
//뒤 알파벳을 앞에다 붙인다. 총횟수는 총길이가 된다.
//i는 인덱스이자 횟수(index+1)로 활용한다.
//진행하다가 같으면 횟수를 반환한다.
for(let i = 0; i < A.length; i++){
A = A.slice(-1) + A.slice(0,-1);
if(A === B) return i +1;
}
//안되면 -1을 반환한다.
return -1;
}
배열 메소드인 slice
에는 인수가 두개가 아닌 하나가 들어갈 수도 있다. slice(a)의 경우 a인덱스부터 끝까지 자른 새 배열을 반환하며 slice(-a)의 경우 끝에서 a개 자른 배열을 반환한다.
//slice에 인수가 하나 들어갔을 때
let arr = [1,2,3,4,5];
console.log(arr.slice(-3)); //[3,4,5]
console.log(arr.slice(2)); //[3,4,5]
같은 하나의 인수지만 양수와 음수일 때 반환값이 다른 메소드라는 것을 생각하자!
다른 사람 풀이중 신기한 풀이를 가져왔다. indexOf는 인수의 문자열을 찾고 있으면 그 인덱스를 , 없으면 -1를 반환한다. 이 분은 이를 이용해서 간단하게 풀었다.
let solution = (a,b) => (b+b).indexOf(a)
문제 : 3x 마을 사람들은 3을 저주의 숫자라고 생각하기 때문에 3의 배수와 숫자 3을 사용하지 않습니다. 3x 마을 사람들의 숫자는 다음과 같습니다. 인수로 n을 주었을때 3x마을에서 n을 어떻게 쓰는지 구하시오.
1 => 1 | 6 => 8
2 => 2 | 7 => 10
3 => 4 | 8 => 11
4 => 5 | 9 => 14
5 => 7 | 10 => 16
이 문제에서 주의할 점은 3의 배수뿐만 아니라 3이 들어간 모든 숫자를 건너 뛰어야 한다는 점이다. 13,30 등 3이 들어간 숫자면 모두 건너 뛰어야 한다.
바로 이 '건너뛴다'는 키워드가 풀이 포인트이다. 숫자는 순서대로 1씩 증가하면서, 3의 배수거나 3이 들어가 있을 때 그 숫자에서 +1을 해주면 된다.
33처럼 3의 배수이자 3이 들어가 있는 숫자더라도 +1을 해주면 된다. 이 말은 즉슨 2가지 조건
- 3의 배수
- 3이 들어있는 수
를 하나라도 만족하면 +1을 해주는 것이다. 그 다음숫자도 계속 이 조건을 검사해야 하기 때문에 반복 횟수가 정해진 for
문보다 반복 횟수를 정하지 않는 while
문을 쓰는 것이 적합하다.
하지만 조건에 만족했을 때 숫자를 건너뛰는 것과 별개로 지속적으로 숫자를 늘려줘야 하므로 for문을 같이 사용한다.
function solution(n) {
let count = 0;
//for문으로 n이 될 때까지 반복문으로 돌린다.
for(let i = 1 ; i <= n ; i++){
count++;
//조건에 맞으면 count를 증가시킨다.
while(count% 3 === 0 || count.toString().includes('3')){ count++;
}
}
return count;
}
최근 이런 문제를 풀다 느낀건데, for문의 i를 단순히 반복횟수가 아닌 리턴 값이나, 하나의 조건으로 활용을 하는 경우가 많은 것 같다.