본문 바로가기

[HackerRank] Sherlock and Anagrams (Javascript)

요즘 머리 환기 겸 간간히 코딩 테스트를 연습하고 있는데 문자열 관련한 문제를 풀던 중 중요한 사실을 하나 알았다.

 

우선 문제는 다음과 같다.

 


문제 설명.

 

주어진 문자열의 부분 문자열 중 Anagram의 개수를 찾는 것.

 

※ Anagram: 문자열의 길이와 포함된 문자의 개수가 같은 두 문자열의 집합

 

예를 들어 'abba'이면, [a, a], [b, b], [ab, ba], [abb, bba]가 Anagram이므로 4를 리턴해야 한다.

 

출처. https://www.hackerrank.com/challenges/sherlock-and-anagrams/problem


아무리 머리를 싸매도 O(n^4)밖에 생각이 안나서 Brute Force로 풀었다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
function isAnagram (A, B) {
  let objA = {}, objB = {};
 
  for (const a of A) {
    !!objA[a] ? objA[a]++ : objA[a] = 1
  }
 
  for (const b of B) {
    !!objB[b] ? objB[b]++ : objB[b] = 1
  }
 
  return Object.keys(objA).every(key => objA[key] === objB[key])
  ? true
  : false
}
 
function compare (str, s) {
  const len = str.length;
 
  let cnt = 0;
  for (let i=0;i<=s.length-len;i++) { 
    const str2 = s.substring(i, i+len);
    if(isAnagram(str, str2)) {
      cnt++
    }
  }
 
  return cnt;
}
 
function sherlockAndAnagrams(s) {
  let result = 0;
 
  for (let i=0;i<s.length;i++) { // 시작 인덱스
    for (let e=1;e < s.length;e++) { // 비쿄할 문자 개수
      if (i+>= s.lengthcontinue;
      let str1 = s.substring(i, i+e); // 비교문자열 하나 선택
 
      result += compare(str1, s.substring(i+1, s.length)) // 나머지 가능성 있는 문자열들과 비교하는 함수, i+1부터 비교 시작
    }
  }
  return result
}
 
const strs = [
  "ifailuhkqqhucpoltgtyovarjsnrbfpvmupwjjjfiwwhrlkpekxxnebfrwibylcvkfealgonjkzwlyfhhkefuvgndgdnbelgruel",
  "gffryqktmwocejbxfidpjfgrrkpowoxwggxaknmltjcpazgtnakcfcogzatyskqjyorcftwxjrtgayvllutrjxpbzggjxbmxpnde",
  "mqmtjwxaaaxklheghvqcyhaaegtlyntxmoluqlzvuzgkwhkkfpwarkckansgabfclzgnumdrojexnrdunivxqjzfbzsodycnsnmw",
  "ofeqjnqnxwidhbuxxhfwargwkikjqwyghpsygjxyrarcoacwnhxyqlrviikfuiuotifznqmzpjrxycnqktkryutpqvbgbgthfges",
  "zjekimenscyiamnwlpxytkndjsygifmqlqibxxqlauxamfviftquntvkwppxrzuncyenacfivtigvfsadtlytzymuwvpntngkyhw",
  "ioqfhajbwdfnudqfsjhikzdjcbdymoecaokeomuimlzcaqkfmvquarmvlnrurdblzholugvwtkunirmnmsatrtbqlioauaxbcehl",
  "kaggklnwxoigxncgxnkrtdjnoeblhlxsblnqitdkoiftxnsafukbdhasdeihlhfrqkfzqhvnsmsgnrayhsyjsniutmgpfjmssfsg",
  "fhithnigqftuzzgpdiquhlsozksxxfreddmsmvqgfgzntphmgggszwtkcbmjsllwtukgqvpvxvmatuanbeossqwtpgzbagaukmta",
  "rqjfiszbigkdqxkfwtsbvksmfrffoanseuenvmxzsugidncvtifqesgreupsamtsyfrsvwlvhtyzgjgnmsowjwhovsmfvwuniasw",
  "dxskilnpkkdxwpeefvgkyohnwxtrrtxtckkdgnawrdjtcpzplywyxmwtemwmtklnclqccklotbpsrkazqolefprenwaozixvlxhu"
  ]
 
for (const str of strs) {
  console.log(sherlockAndAnagrams(str));
}
 
/**
399
471
370
403
428
412
472
457
467
447
 */
 
 

처음엔 가장 긴 Task인 위의 예시만 제한 시간 통과를 못해서 혹시나 Brute Force가 아닌가 싶어 걱정했는데 isAnagram함수를 for of문이 아니라 Array.every 메소드를 사용하니까 되었다.

 

Array.every 메소드는 콜백함수에서 false가 나면 그 즉시 순회를 멈추고 false를 리턴하기 때문에 단순 비교보다 더 빠르다.

 

따라서 이러한 배열 관련 메소드들을 적절한 상황에서 잘 활용하면 알고리즘 테스트 Time Limit을 더욱 잘 통과할 수 있을 거라는 걸 깨달았다.

'Today I Learn > 알고리즘' 카테고리의 다른 글

해쉬 테이블  (0) 2020.03.29
[그래프탐색] DFS/BFS  (0) 2020.03.28
[정렬] Javascript로 정렬 알고리즘 공부하기  (0) 2020.03.16