카테고리 없음

알고리즘 50번 - 가장 가까운 같은 글자

GREEN나무 2025. 1. 2. 09:58
728x90

URL : https://school.programmers.co.kr/learn/courses/30/lessons/142086

JS

문제

문제 설명
문자열 s가 주어졌을 때, s의 각 위치마다 자신보다 앞에 나왔으면서, 자신과 가장 가까운 곳에 있는 같은 글자가 어디 있는지 알고 싶습니다.
예를 들어, s="banana"라고 할 때,  각 글자들을 왼쪽부터 오른쪽으로 읽어 나가면서 다음과 같이 진행할 수 있습니다.

b는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
a는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
n은 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
a는 자신보다 두 칸 앞에 a가 있습니다. 이는 2로 표현합니다.
n도 자신보다 두 칸 앞에 n이 있습니다. 이는 2로 표현합니다.
a는 자신보다 두 칸, 네 칸 앞에 a가 있습니다. 이 중 가까운 것은 두 칸 앞이고, 이는 2로 표현합니다.
따라서 최종 결과물은 [-1, -1, -1, 2, 2, 2]가 됩니다.

문자열 s이 주어질 때, 위와 같이 정의된 연산을 수행하는 함수 solution을 완성해주세요.

제한사항
1 ≤ s의 길이 ≤ 10,000
s은 영어 소문자로만 이루어져 있습니다.


입출력 예
  s                result
"banana"   [-1, -1, -1, 2, 2, 2]
"foobar"     [-1, -1, 1, -1, -1, -1]

 


계획

문자열을 배열로 만들고 문자열을 훑는 반복문 안에 조건을 걸어 이전에 마지막므로 동일한 문자가 나온 위치와의 거리를 새 배열에 추가하기. 동일한 문자가 없는 경우 -1 추가.

새 배열을 반환하기


참고, 풀이

findLastIndex() 사용법

const index = numbers.findLastIndex(num => num % 2 === 0);
function solution(s) {
    let arrS = [...s];
    let arrAnswer = [];
    let arrTemp = [];
    arrS.forEach((v) => {
        arrAnswer.push(arrTemp.findLastIndex((li) => li === v));
        arrTemp.push(v);
    });
    console.log(arrTemp);
    return arrAnswer;
}

//const index = numbers.findLastIndex(num => num % 2 === 0);
/**
 * 입출력 예
  s                result
"banana"   [-1, -1, -1, 2, 2, 2]
"foobar"     [-1, -1, 1, -1, -1, -1]
 */
const b = "banana";
const f = "foobar";

console.log(solution(b)); // 오답  [ -1, -1, -1, 1, 2, 3 ]
console.log(solution(f));

마지막 인덱스와 직전에 등장한 동일 문자 위치의 차를 arrAnswer에 추가해야 합니다.

function solution(s) {
    let arrS = [...s];
    let arrAnswer = [];
    let arrTemp = [];

    arrS.forEach((v, i) => {
        // 현재 문자가 arrTemp에서 마지막으로 등장한 위치 찾기
        let lastIndex = arrTemp.findLastIndex((char) => char === v);
        arrAnswer.push(lastIndex === -1 ? -1 : i - lastIndex); // 인덱스 차이 계산
        arrTemp.push(v); // arrTemp에 현재 문자 추가
    });
    console.log(arrTemp);
    return arrAnswer;
}

 

TypeError: arrTemp.findLastIndex is not a function

최신버전이 아니라 사용 할 수 없는 것 같습니다.

 


function solution(s) {
    let arrAnswer = [];
    let lastIndexMap = {}; // 문자의 마지막 등장 위치를 저장

    [...s].forEach((char, idx) => {
        if (lastIndexMap[char] !== undefined) {
            arrAnswer.push(idx - lastIndexMap[char]); // 현재 인덱스 - 마지막 등장 인덱스
        } else {
            arrAnswer.push(-1); // 처음 등장하는 경우
        }
        lastIndexMap[char] = idx; // 마지막 등장 위치 갱신
    });

    console.log(lastIndexMap);
    return arrAnswer;
}

코드 간략화하기

function solution(s) {
    let lastIndexMap = {}; // 문자의 마지막 등장 위치 저장
    return [...s].map((char, idx) => {
        let distance = lastIndexMap[char] !== undefined ? idx - lastIndexMap[char] : -1;
        lastIndexMap[char] = idx; // 마지막 등장 위치 갱신
        return distance;
    });
}

다른사람 답

function solution(s) {
    const map = new Map();
    return [...s].map((char, i) => {
        const result = map.has(char) ? i - map.get(char) : -1;
        map.set(char, i);
        return result;
    });
}

코드 설명
map 객체를 사용:
        각 문자의 마지막 인덱스를 저장합니다.
        키는 문자, 값은 해당 문자가 마지막으로 등장한 위치입니다.
map 메서드와 인덱스 계산:
       문자열 s를 배열로 변환하고, map()을 사용해 각 문자를 처리합니다.
        문자가 map에 존재하면 현재 인덱스와 저장된 인덱스의 차이를 계산합니다.
        문자가 처음 등장하는 경우 -1을 반환합니다.
결과 업데이트:
        현재 문자의 인덱스를 map에 저장해 다음에 동일 문자가 등장할 때 참조합니다.

const solution = (s) =>
  [...s].map((char, i) => {
    const count = s.slice(0, i).lastIndexOf(char);
    return count < 0 ? count : i - count;
  });

 

 

  • 주요 동작: 문자열에서 각 문자에 대해 이전 등장 위치와의 차이를 계산.
  • 코드의 특징: 간결하지만 긴 문자열에서는 성능 저하 가능 (O(n²)).

 

1. const solution = (s) => { ... }

  • 문자열 s를 입력으로 받아 처리하는 함수.
  • 화살표 함수와 map을 활용해 간결하게 구현.

2. [...s].map((char, i) => { ... })

  • 문자열 s를 배열로 변환:
    • 예: s = "hello" → [...s] = ['h', 'e', 'l', 'l', 'o'].
  • map을 사용해 배열의 각 문자(char)와 인덱스(i)를 순회하며 결과 계산.

3. const count = s.slice(0, i).lastIndexOf(char);

  • 문자 char가 현재 인덱스 i 이전에 마지막으로 등장한 위치를 계산:
    • s.slice(0, i): 문자열의 0부터 i-1까지 자름.
      • 예: s = "abca", i = 3 → s.slice(0, 3) = "abc".
    • .lastIndexOf(char): 잘라낸 부분 문자열에서 문자 char가 마지막으로 등장한 위치를 반환.
      • char가 없으면 -1 반환.
      • 예: "abc".lastIndexOf('a') = 0, "abc".lastIndexOf('d') = -1.

4. return count < 0 ? count : i - count;

  • count < 0: 이전에 문자가 등장하지 않았으면 -1 반환.
  • 그렇지 않으면 i - count를 계산하여 반환.
    • 예:
      • count = -1 → return -1.
      • count = 0 (문자가 이전에 등장) → return i - count.