프라이D
프라이Develog(❁´◡`❁)
프라이D
전체 방문자
오늘
어제
  • ALL (378)
    • TDD, Cleancode with JavaScr.. (5)
    • 프로젝트 (32)
      • work (3)
      • 직접 만드는 기술 블로그 (2)
      • 데일리 옥션 (19)
      • 모락모락 (8)
    • Computer Science (1)
    • Algorithm & 자료구조 (94)
      • 알고리즘 w.JavaScript (53)
      • 자료구조 (5)
      • (인프런) 자바스크립트 알고리즘 문제풀이 (34)
    • JavaScript (45)
      • JavaScript (41)
      • 모던 자바스크립트 Deep Dive (4)
    • WEB (13)
    • 회고 (12)
    • TIL (109)
    • WIL (7)
    • Stacks (20)
      • React.js (6)
      • Next.js (1)
      • Redux (3)
      • Node.js (2)
      • GIT (2)
      • SAP (1)
    • 15일 메이킹 프로젝트 (15)
    • 이전 기록 (14)
    • ETC. (5)
    • ---------------2021 (6)
      • 내일배움단-웹개발 5주 (2)
      • 정보처리기사 (4)

블로그 메뉴

  • 홈
  • 태그
  • 미디어로그
  • 위치로그
  • 방명록

공지사항

인기 글

태그

  • JavaScript
  • 국비지원
  • 내일배움카드
  • MySQL
  • 투포인터알고리즘
  • 자바스크립트비트마스크
  • nomadcoder
  • 스파르타코딩클럽
  • 2023 인프콘 후기
  • 비트마스크
  • 자바스크립트알고리즘
  • nomadcoders
  • 내일배움단
  • Til
  • 모던자바스크립트딥다이브
  • 코드스테이츠
  • 코딩프로젝트
  • 알고리즘
  • 자바스크립트
  • vanilaJS

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
프라이D

프라이Develog(❁´◡`❁)

[알고리즘] 모든 아나그램 찾기
Algorithm & 자료구조/(인프런) 자바스크립트 알고리즘 문제풀이

[알고리즘] 모든 아나그램 찾기

2022. 9. 18. 14:08

문제

S문자열에서 T문자열과 아나그램이 되는 S의 부분 문자열의 개수를 구하는 프로그램을 작성하세요. 아나그램 판별시 대소문자가 구분됩니다. 부분 문자열은 연속된 문자열이어야 합니다.

 

입력 : 두 문자열 S 와 T, T 문자열의 길이는 S문자열보다 작거나 같습니다.

출력 : S 단어에 T문자열과 아나그램이 되는 부분 문자열의 개수를 출력합니다. 

풀이

이 문제는 슬라이딩 윈도우 알고리즘과 맵 객체를 활용하여 풀 수 있는 문제이다.

  • T 와 S의 0부터 T.length - 1 까지의 문자열에 대해서 각 문자를 키로, 포함하고 있는 갯수를 밸류로 하는 맵 객체를 만든다.
  • 두 개의 포인터로 T의 길이만큼 범위를 잡아서 S 문자열을 이동하며 T와 S 문자열의 일부분을 비교한다.
  • T 길이 만큼 범위를 잡는다는 것은, 두 개의 포인터 변수 left 와 right 가 있을 때 left가 0, right가 2 이면, right를 하나씩 더해가며 동시에 left도 더하는 것을 의미한다. 이런 식으로 범위를 지정하면 중첩 for문을 돌아서 비교하는 것 보다 시간복잡도가 개선된다.

출처 : https://towardsdev.com/sliding-window-algorithm-145f8e201a64

const S = 'bacaAacba';
const T = 'abc';

// 문자열이 주어지면 해시 맵을 생성하는 함수
function generateHash(str) {
  let hash = new Map();

  // 문자열을 l로 반복해서, 맵 객체에 키가 있으면 값을 추가,
  // 존재하지 않으면 값을 1로 셋팅
  for (l of str) {
    if (hash.has(l)) {
      let value = hash.get(l) + 1;
      hash.set(l, value);
    } else {
      hash.set(l, 1);
    }
  }

  return hash;
}

// 두 맵 객체가 주어졌을 때 동일 여부 비교 함수
function compareMaps(map1, map2) {
  // 먼저 사이즈가 같은지 판단하고,
  if (map1.size !== map2.size) {
    return false;
  }
  // 사이즈가 같은 경우 한 쪽의 키와 밸류를 가지고
  // 키가 있는지 여부 확인, 값이 같은지 여부를 확인한다.
  else {
    for (let [key, val] of map1) {
      if (!map2.has(key) || map2.get(key) !== val) return false;
    }
  }
  return true;
}

// 풀이 코드
function solution1(S, T) {
  const Tlen = T.length;
  const Slen = S.length;

  // 비교 대상인 T 문자열에 대한 맵 객체 생성,
  // T의 길이 만큼의 범위를 가진 S의 부분 문자열에 대한 맵 객체 생성
  let tH = generateHash(T);
  let sH = generateHash(S.substring(0, Tlen - 1));

  // 같을 경우 증감시킬 카운터와, lt 포인터를 0으로 셋팅한다.
  let count = 0;
  let lt = 0;
  // lt = 0, rt = 새로운 값을 추가하면서 비교 시작
  for (let rt = Tlen - 1; rt < Slen; rt++) {
    // sH 가 S[rt] 키를 가지고 있다면, 그 값의 + 1,
    // 키가 존재하지 않으면 값을 1로 설정
    if (sH.has(S[rt])) sH.set(S[rt], sH.get(S[rt]) + 1);
    else sH.set(S[rt], 1);

    // tH와 sH 두 맵을 비교해 같으면 카운트를 증가
    if (compareMaps(sH, tH)) count++;

    //S[lt] 포인터에 해당하는 값을 -1 한 뒤,
    sH.set(S[lt], sH.get(S[lt]) - 1);
    // 만약 그 키의 값이 0이라면, 존재하지 않는 문자열이므로 키 자체를 삭제한다.
    if (sH.get(S[lt]) === 0) sH.delete(S[lt]);
    // 윈도우가 앞으로 한 칸 이동했으므로 lt 를 증감한 뒤 해당 반복이 마무리된다.
    lt++;
  }

  return count;
}

const result = solution1(S, T);
console.log(result);
저작자표시 (새창열림)

'Algorithm & 자료구조 > (인프런) 자바스크립트 알고리즘 문제풀이' 카테고리의 다른 글

[알고리즘] 마구간 정하기  (2) 2022.10.11
[알고리즘] 최대매출  (0) 2022.09.09
[알고리즘] 연속 부분수열 2 (투포인터 알고리즘)  (0) 2022.09.09
[알고리즘] 모든 아나그램 찾기(해쉬, 투포인터, 슬라이딩 윈도우)  (0) 2022.04.20
[알고리즘] 순열구하기  (0) 2022.03.19
    'Algorithm & 자료구조/(인프런) 자바스크립트 알고리즘 문제풀이' 카테고리의 다른 글
    • [알고리즘] 마구간 정하기
    • [알고리즘] 최대매출
    • [알고리즘] 연속 부분수열 2 (투포인터 알고리즘)
    • [알고리즘] 모든 아나그램 찾기(해쉬, 투포인터, 슬라이딩 윈도우)
    프라이D
    프라이D
    틀린내용 정정 및 개선사항은 언제든지 댓글 달아주세요 :D

    티스토리툴바