[js] 조건에 맞게 수열 변환하기 2 (lv.0, 정답률 83%)

sookyoung.k·2024년 5월 24일
0
post-thumbnail

정수 배열 arr가 주어집니다. arr의 각 원소에 대해 값이 50보다 크거나 같은 짝수라면 2로 나누고, 50보다 작은 홀수라면 2를 곱하고 다시 1을 더합니다.

이러한 작업을 x번 반복한 결과인 배열을 arr(x)라고 표현했을 때, arr(x) = arr(x + 1)인 x가 항상 존재합니다. 이러한 x 중 가장 작은 값을 return 하는 solution 함수를 완성해 주세요.

단, 두 배열에 대한 "="는 두 배열의 크기가 서로 같으며, 같은 인덱스의 원소가 각각 서로 같음을 의미합니다.

제한사항

  • 1 ≤ arr의 길이 ≤ 1,000,000
    - 1 ≤ arr의 원소의 값 ≤ 100

나의 풀이

function solution(arr) {
    // 배열 바꾸기
    const changeArr = (arr) => {
        return arr.map((el) => {
            if (el >= 50 && el % 2 == 0) return el / 2;
            else if (el < 50 && el % 2 != 0) return el * 2 + 1;
            else return el;
        })
    }
    
    // 배열 바꾸는거 반복하기 
    const again = (arr, x) => {
        let newArr = [...arr];
        for (let i=0; i<x; i++) {
            newArr = changeArr(newArr);
        }
        return newArr;
    }
    
    // 배열이 이전 배열과 같은지 확인하기 
    const isEqual = (a, b) => {
        return a.length === b.length && a.every((val, i) => val === b[i]);
    }
    
    // 결과 값 초기화 
    let result = 0;
    
    // 반복 작업으로 결과 도출
    for (let i = 0; ; i++) {
        if (isEqual(again(arr, i), again(arr, i+1))) {
            result = i;
            break;
        }
    }
    return result; 
}

뭔가 진짜 안 풀려서 빡쎄게 풀었는데... 혹시라도 까먹을까봐 주석도 달아놨었다.

  • 먼저 배열을 바꾸는 함수를 하나 만들었다. 그래서 각각 경우의 수에 맞게 배열을 바꿔주도록 map()을 사용해서 조건을 걸어주었다.
  • 그리고 배열을 바꾸는 함수를 또 만들었다. 원본 배열을 바꾸지 않기 위해서 새로 newArr을 선언했고, for문을 돌며 위에서 만든 changeArr()을 반복해주었다.
  • 그리고 배열이 이전 배열과 같은지 확인하는 함수도 만들었다. 이쯤되면 함수성애자다. a와 b 배열의 길이가 같고, every() 를 통해서 동일한 배열인지 확인을 해준다.
  • 휴 거의 다 왔다. 결과를 저장할 result 변수를 하나 선언한 뒤
  • for문을 통해서 앞서 만든 함수를 다 때려넣고 정답에 맞는 순번이 돌아올 때까지 조건을 돌아준다. 무한 for문이기 때문에 결과를 result에 저장한 후 break를 걸어준다.

다른 풀이 1

function solution(arr) {
    var answer = 0;
    let before = [-1];

    while(!arr.every((e,idx) => e == before[idx])) {
        before =[...arr];

        arr = arr.map(e => {
            if(e >= 50 & e % 2 == 0)
                return e / 2;
            if(e < 50 & e % 2 != 0)
                return e * 2 + 1;
            return e;
        })
        answer++;
    }
    return answer - 1;
}
  • answer 변수를 0으로 초기화 한다 (횟수 카운트)
  • before 배열을 -1로 초기화한다 (이전 반복에서의 arr 상태 저장)
  • arr의 모든 요소가 before의 해당 인덱스 요소와 같을 때까지 반복한다
    - before 배열을 arr의 현재 상태로 업데이트
    • 배열의 각 요소에 대해 요소가 50 이상이고 짝수인 경우 해당 요소를 2로 나눈다
    • 요소가 50 미만이고 홀수인 경우 해당 요소를 2배하고 1을 더한다
    • 그 외의 경우는 변하지 않는다
  • 반복이 종료되면 마지막에 증가된 answer 값에서 1을 빼서 반환한다 (마지막 반복에서는 실제로 arr에 변화가 없었기 때문

다른 풀이 2

function solution(arr, n = 0) {
    while(!arr.every(x => (x >= 50 && x % 2 === 1) || (x < 50 && x % 2 === 0))) {
        arr = arr.map(x => {
            if (x >= 50 && x % 2 === 0) return x / 2;
            if (x < 50 && x % 2 === 1) return x * 2 + 1;
            return x;
        })
        n++;
    }
    return n;
}
  • while 문에서 반복조건을 설정한다. 이 때 every 메서드를 사용하여 배열의 모든 요소가 특정 조건을 만족하는지 확인한다
    - 요소가 50 이상이고 홀수이거나
    • 요소가 50 미만이고 짝수이거나
    • 조건을 만족하지 않는 요소가 하나라도 있으면 반복 계속
  • map()을 이용해서 배열의 각 요소를 변환한다 (조건은 위와 같음 당연함)
  • 반복 횟수(n)를 증가시킨다
  • 모든 요소가 조건을 만족할 때 반복 종료 후 n을 반환한다
profile
영차영차 😎

0개의 댓글