티스토리 뷰
오늘 리뷰할 문제는 30번 substring with concatenation of all words이다.
https://leetcode.com/problems/substring-with-concatenation-of-all-words/description/
Substring with Concatenation of All Words - LeetCode
Can you solve this real interview question? Substring with Concatenation of All Words - You are given a string s and an array of strings words. All the strings of words are of the same length. A concatenated substring in s is a substring that contains all
leetcode.com
주어진 문자열 s와, 같은길이의 단어들의 목록(words)가 주어졌을 때, s의 substring중 words안의 단어의 재배치로 얻을 수 있는 substring의 시작위치와 종료위치를 찾는 문제이다.
같은길이의 단어들의 목록이므로, s의 substring도 시작위치가 정해지면 같은 길이로 words의 갯수만큼 만들면 해당 substring이 가지고 있는 단어의 목록을 얻을 수 있고. 해당 단어의 목록과 words를 비교해서 결과를 찾으면 된다.
추가로 비교를 해야할 때는, substring의 시작단어와, 다음단어만 가지고 다음 substring의 단어의 목록을 구할 수 있다.
그리고 단어의 길이만큼 시작 index를 달리 가져가면서 iteration을 돌리면 모든 substring에 대해서 확인을 할 수 있다.
Dictionary로 직접 구현한 코드
class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
words_map_count = dict()
for word in words:
if word in words_map_count:
words_map_count[word] += 1
else:
words_map_count[word] = 1
word_count = len(words)
word_len = len(words[0])
results = []
for i in range(word_len):
# initialize first sequence
start_index = i
end_index = i + word_len * word_count
if end_index > len(s):
break
match_map_count = dict()
for j in range(word_count):
word = s[start_index + j * word_len : start_index + (j + 1) * word_len]
if word in match_map_count:
match_map_count[word] += 1
else:
match_map_count[word] = 1
if match_map_count == words_map_count:
results.append(start_index)
start_index = start_index + word_len
end_index = end_index + word_len
while end_index <= len(s):
before_word = s[start_index - word_len : start_index]
after_word = s[end_index - word_len : end_index]
if before_word in match_map_count:
match_map_count[before_word] -= 1
if match_map_count[before_word] == 0:
del match_map_count[before_word]
if after_word in match_map_count:
match_map_count[after_word] += 1
else:
match_map_count[after_word] = 1
if match_map_count == words_map_count:
results.append(start_index)
start_index = start_index + word_len
end_index = end_index + word_len
return results
속도는 잘 나오는데, 메모리가 조금 많이 잡아먹는 느낌이 있다.
다른 사람의 코드를 비교했을 때, collection.Counter를 사용하니 코드가 조금 더 깔끔해셔서 반영한 것은 다음과 같다.
class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
words_map_count = dict()
for word in words:
if word in words_map_count:
words_map_count[word] += 1
else:
words_map_count[word] = 1
word_count = len(words)
word_len = len(words[0])
results = []
for i in range(word_len):
# initialize first sequence
start_index = i
end_index = i + word_len * word_count
if end_index > len(s):
break
match_map_count = dict()
for j in range(word_count):
word = s[start_index + j * word_len : start_index + (j + 1) * word_len]
if word in match_map_count:
match_map_count[word] += 1
else:
match_map_count[word] = 1
if match_map_count == words_map_count:
results.append(start_index)
start_index = start_index + word_len
end_index = end_index + word_len
while end_index <= len(s):
before_word = s[start_index - word_len : start_index]
after_word = s[end_index - word_len : end_index]
if before_word in match_map_count:
match_map_count[before_word] -= 1
if match_map_count[before_word] == 0:
del match_map_count[before_word]
if after_word in match_map_count:
match_map_count[after_word] += 1
else:
match_map_count[after_word] = 1
if match_map_count == words_map_count:
results.append(start_index)
start_index = start_index + word_len
end_index = end_index + word_len
return results
속도가 살짝 느려지는데, 조금 더 이해하기 편한 것 같아서 좋다.
다른 사람들의 코드를 봤을 때 iteration을 돌 때 중간 결과물을 재사용하지 않고, 모든 substring에 대해서 매번 word의 목록을 계산해서 비교하는 경우가 있더라.
time complexity를 계산해보면 (len s = S, len words: N, len or word: M)
모든 substring에 대해서 매번 word 목록 계산해서 비교하는 경우
Counter 만드는데 = O(N)
Check Substring 하는데 = O(N)
Check Substring 횟수 = O(S) = O(N)*O(S)
내 Timecomplexity를 계산해보자
Counter 만드는데 = O(N)
for loop 한번에
첫 Substring 만드는데 = O(N)
비교하는데 드는 비용 = O(M)
비교 횟수 = O(S/M)
for loop 횟수는 O(M)
O(N) + O(M) * (O(N) + O(M) * O(S/M)) = O(N) + O(MN) + O(SM) = O(M(S+N)) 이다.
내게 조금 더 나은 것을 볼 수 있다.
'개발 > 알고리즘' 카테고리의 다른 글
[leetcode 매일풀기] 37. sudoku solver (2) | 2023.11.30 |
---|---|
[leetcode 매일 풀기] 32 longest valid parentheses (0) | 2023.11.29 |
[leetcode 매일 풀기]25 reverse nodes in k group (1) | 2023.11.27 |
[leetcode 매일 풀기] 23. merge k sorted list (2) | 2023.11.26 |
[leetcode 매일 풀기] 10. regular expression matching (2) | 2023.11.25 |
- Total
- Today
- Yesterday
- leetcode 매일풀기
- otel
- binary tree maximum path sum
- leetcode
- mlse
- permutation sequence
- hard mode challenge
- sudoku solver
- wildcard matching
- substring with concatenation of all words
- 알고리즘
- palindrome partitioning 2
- first missing positive
- distinct subsequences
- datalakehouse
- 개발자 글쓰기
- word ladder 2
- best time to buy and sell stock 3
- text justification
- 글또 10기
- maximum rectangle
- longest valid parentheses
- valid number
- 가상면접 사례로 배우는 대규모 시스템 설계
- scramble string
- leetcode 매일 풀기
- 회고
- slay the spire에 진심인편
- n queens 2
- Python
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |