[CodeSignal] 코딩테스트 준비

Yunhye Park·2024년 3월 21일

지식 습득

목록 보기
9/11
post-thumbnail

코드시그널 첫 사용기

덜컥 서류를 붙어버리고(?) 코딩테스트를 보기까지 일주일 안 되는 시간이 남았다. 백준, 프로그래머스에서 살짝 맛보기처럼 문제를 풀어봤는데 코드시그널은 처음 들어보는 플랫폼이었다. 글로벌 기반이라선지 모든 UI가 영어로 이루어졌다.

문제1. palindrome

Given the string, check if it is a palindrome.

Example

For inputString = "aabaa", the output should be
solution(inputString) = true;
For inputString = "abac", the output should be
solution(inputString) = false;
For inputString = "a", the output should be
solution(inputString) = true.

Input/Output

[execution time limit] 4 seconds (js)

[memory limit] 1 GB

[input] string inputString
A non-empty string consisting of lowercase characters.

Guaranteed constraints:
1 ≤ inputString.length ≤ 105.

[output] boolean
true if inputString is a palindrome, false otherwise.

즉 주어진 문자열을 역순으로 바꿔도 원본 문자열과 같을 때 true, 아닐 때 false.

트러블 슈팅

역순이라고 해서 가장 먼저 떠오른 건 reverse 메서드였다. 그런데 이건 배열 메서드라서 문자열엔 사용할 수 없으니 문자열을 배열로 바꾸고, 배열을 비교하는 게 좋겠다는 생각에 이르렀다.

function solution(inputString) {
    const arrString = Array.from(inputString); // 배열로
    const reversedArrString = arrString.reverse(); // 배열 뒤집기
    return compareArr(arrString, reversedArrString); // 비교
}

function compareArr(arr1, arr2) {
    return JSON.stringify(arr1) === JSON.stringify(arr2);
}

하지만 이렇게 작성하고 보니, 테스트 케이스의 일부는 통과하지 못한다.

디버깅

    console.log(arrString); // [ 'c', 'a', 'b', 'a' ]
    console.log(reversedArrString); // [ 'c', 'a', 'b', 'a' ]

콘솔 찍어보니 test failed인 것들은 원본 배열과 뒤집은 배열 모두 후자로 나온다.

원인

reverse는 원본 배열을 변경한다.

해결

function solution(inputString) {
    const arrString = Array.from(inputString); // 배열로 변환
    const reversedArrString = Array.from(inputString).reverse(); // 배열 뒤집기
    return compareArr(arrString, reversedArrString); // 비교
}

function compareArr(arr1, arr2) {
    return JSON.stringify(arr1) === JSON.stringify(arr2);
}

원본 배열이 아닌 새로운 배열을 만들어 이를 reverse로 변형한다.

문자열 역순 만들기, 다른 방법은 없을까?

이 문제는 다른 말로 하자면 '문자열을 역순으로 만들어 비교'하기다. 내가 풀이한 방식이 최선은 아니라는 생각이 들었다.

  1. Array.from +reverse + JSON.stringfy

문자열 -> 배열 -> 문자열은 굉장히.. 비효율적이다. 문자열인 것을 기껏 배열로 바꾸고 다시 문자열로 바꾸는 거니까. 게다가 배열 객체를 비교할 일이 자주 있다면 함수로 모듈화(compareArr)해서 쓰는 건 좋지만, 간단한 상황에서는 번거로운 것 같다.

다른 방법을 알아보았다.

  1. split + reverse + join
  • split : 문자열을 배열의 요소로 반환
  • join : 배열의 요소를 합쳐 문자열로 반환

이렇게 풀이하면 코드가 아래처럼 훨씬 간결하다!

function solution(inputString) {
    const arrString = inputString.split("").join();
    const reversedArrString = inputString.split("").reverse().join();
  
    return arrString === reversedArrString;
}

느낀점

reverse 때문에 string을 다시 가져와야 한다는 사실이 좀 아쉽지만, 그래도 문자열로 다시 바꾸는 함수를 만드는 대신 내장 메서드를 사용함으로써 좀더 간단하게 처리할 수 있었다.

배열을 문자열로 바꿀 땐 JSON.stringfy가 가장 간단한 비교 방식이었는데 문자열을 배열로 바꿀 땐 또 다른 메서드가 유용하다. 이처럼 상황이 조금만 달라도 사용할 조합이 달라지는 걸 보면서 데이터 타입을 명시화하고 특징을 알아두는 게 중요하다고 느낀다.


문제2. 인접한 두 수의 최대곱

Given an array of integers, find the pair of adjacent elements that has the largest product and return that product.

Example

For inputArray = [3, 6, -2, -5, 7, 3], the output should be
solution(inputArray) = 21.

7 and 3 produce the largest product.

Input/Output

[execution time limit] 4 seconds (js)
[memory limit] 1 GB
[input] array.integer inputArray

An array of integers containing at least two elements.

Guaranteed constraints:
2 ≤ inputArray.length ≤ 10,
-1000 ≤ inputArray[i] ≤ 1000.

[output] integer
The largest product of adjacent elements.

즉 배열 요소 중 인접한 두 수의 최대곱을 구하라는 문제.

트러블 슈팅

우선 배열 요소 중 두 수를 비교하는 상황이니까 순회를 해야겠다는 생각이 들었다. 게다가 '인접한'이라는 조건 덕분에 모든 수를 순회하며 최댓값을 찾을 필요 없이, 인덱스로 접근하면 된다.

요소에 음의 정수와 양의 정수 모두가 존재한다. 고로 최대 곱을 판가름 할 기준이 될 숫자는 이를 고려해야 한다. 자바스크립트의 Number.NEGATIVE_INFINITY는 음의 무한대를 나타내기 때문에 0이 아닌 수를 포함해서 로직을 짤 때 유용하다.

음의 무한대 : 무한히 작은 값. 쉽게 말해 어떤 상황에서든 최소값일 값.

function solution(inputArray) {
    const standardNum = Number.NEGATIVE_INFINITY; // 기준
    for(let i = 0; i < inputArray.length; i++) {
        const mulNum = inputArray[i] * inputArray[i + 1];
		if (mulNum > standardNum) return mulNum;
    };
    return standardNum; 
}

이렇게 작성하니 무조건 인덱스 0과 1 값의 곱을 리턴한다.

원인

음의 무한대는 언제나 최소값이므로 갱신이 필요하다. 두 수를 곱한 결과(mulNum)를 바로 리턴할 게 아니라, 기준이 될 값을 갱신해주며 반복문을 순회할 수 있도록 로직을 짜야 한다.

해결

function solution(inputArray) {
    let standardNum = Number.NEGATIVE_INFINITY; // 기준
    for(let i = 0; i < inputArray.length - 1; i++) {
        const mulNum = inputArray[i] * inputArray[i + 1];
        if(mulNum > standardNum) {
        standardNum = mulNum;           
        }
    };
    return standardNum; 
}
  1. 기준이 될 변수(standardNum)는 재할당 가능한 let 키워드로 고쳤다. const는 상수라서 재할당이 불가하니까.

  2. 마지막 인덱스 + 1은 배열에서 존재하지 않는 인덱스이므로, length - 1만큼 순회한다.

느낀점

배열 순회의 핵심은 횟수가 아닐까 싶다. 연도(year)를 세기(century)로 바꾸는 문제도 풀었는데 여기서도 100 단위의 숫자를 동일하게 취급하기 위해서 Math.floor를 사용했고, 특정 세기의 첫 연도(ex. 300)를 고려하는 게 필요했다.
위 문제도 마찬가지다. 마지막 인덱스에서 한 번 더 나아가도록 값을 정의했으므로 요소 크기보다 하나 더 작아야 한다.


문제 난이도가 생각보단 쉽지 않다. 근데 재밌다!

profile
일단 해보는 편

0개의 댓글