2466. Count Ways To Build Good Strings
내 코드
MLE.. Solution 참고.
class Solution {
public:
int countGoodStrings(int low, int high, int zero, int one) {
for(int i{};i<zero;++i) {
zeros.push_back('0');
}
for(int i{};i<one;++i) {
ones.push_back('1');
}
l = low, h = high;
makeString("");
return answer;
}
private:
int answer{};
string zeros, ones;
int l, h;
void makeString(string curr) {
if(l <= curr.size()) {
++answer;
}
if(curr.size() + zeros.size() <= h) makeString(curr + zeros);
if(curr.size() + ones.size() <= h) makeString(curr + ones);
}
};
Solution
Approach 1: Dynamic Programming (Iterative).
- 4ms, 11.70MB
- Complexity
- Time Complexity:
- Space Complexity:
// Java Code -> C++ Code
class Solution {
public:
int countGoodStrings(int low, int high, int zero, int one) {
// dp[i]는 길이가 i인 좋은 문자열의 수를 저장
vector<int> dp(high + 1, 0);
dp[0] = 1; // 길이가 0인 문자열의 수는 1
const int mod = 1'000'000'007;
// 각 길이 `end`에 대해 반복
for (int end = 1; end <= high; ++end) {
// 현재 문자열을 0 `zero`개 또는 1 `one`개로 만들 수 있는지 확인
if (end >= zero) {
dp[end] += dp[end - zero];
}
if (end >= one) {
dp[end] += dp[end - one];
}
dp[end] %= mod;
}
// 유효한 길이 [low ~ high]의 문자열 수를 합산
int answer = 0;
for (int i = low; i <= high; ++i) {
answer += dp[i];
answer %= mod;
}
return answer;
}
};
GPT
이 코드는 주어진 제약 조건에 따라 “좋은 문자열”을 생성할 수 있는 방법의 수를 계산합니다. “좋은 문자열”은 과 을 사용하여 구성되며, 특정 개수의 또는 을 더하여 생성됩니다. 이 문제는 동적 프로그래밍(DP) 을 사용해 해결합니다.
문제 정의
주어진 조건
- : “좋은 문자열”의 최소 길이.
- : “좋은 문자열”의 최대 길이.
- : 문자열 끝에 개의 을 추가 가능.
- : 문자열 끝에 개의 을 추가 가능.
목표
- 길이가 인 “좋은 문자열”의 총 개수를 계산합니다.
- 결과를 로 나눈 나머지를 반환합니다.
코드 설명
1. DP 배열 초기화
vector<int> dp(high + 1, 0);
dp[0] = 1; // 길이가 0인 문자열의 수는 1
dp[i]: 길이가 인 “좋은 문자열”의 수를 저장.- 길이가 인 문자열은 유일하므로 초기값 .
2. DP 점화식
for (int end = 1; end <= high; ++end) {
if (end >= zero) {
dp[end] += dp[end - zero];
}
if (end >= one) {
dp[end] += dp[end - one];
}
dp[end] %= mod;
}
- : 현재 계산 중인 문자열의 길이.
- 점화식:
- 인 경우:
- 끝에 개의 을 추가하여 길이 문자열을 생성.
- .
- 인 경우:
- 끝에 개의 을 추가하여 길이 문자열을 생성.
- .
- 로 나머지를 구해 오버플로우를 방지.
- 인 경우:
3. 유효한 길이의 합산
int answer = 0;
for (int i = low; i <= high; ++i) {
answer += dp[i];
answer %= mod;
}
- 길이가 인 문자열의 수를 합산.
- 로 나머지를 구해 최종 결과를 계산.
시간 및 공간 복잡도
시간 복잡도
- DP 배열 계산:
- : 각 에 대해 반복.
- 결과 합산:
- : 범위의 합산.
총 시간 복잡도: .
공간 복잡도
- DP 배열: .
작동 예시
입력:
low = 3, high = 3, zero = 1, one = 2
계산 과정:
-
초기화:
-
DP 배열 채우기:
- : .
. - : .
. - : .
.
- : .
-
결과 합산:
- 길이 만 포함하므로 .
출력:
3
확장 예시
입력:
low = 2, high = 4, zero = 1, one = 2
계산 과정:
-
초기화:
-
DP 배열 채우기:
- : .
. - : .
. - : .
. - : .
.
- : .
-
결과 합산:
- .
출력:
10
Approach 2: Dynamic Programming (Recursive)
- 7ms, 14.82MB
- Complexity
- Time Complexity:
- Space Complexity:
// Java Code -> C++ Code
class Solution {
private:
vector<int> dp;
const int mod = 1'000'000'007;
// 길이가 `end`인 좋은 문자열의 수를 계산
int dfs(int end, int zero, int one) {
if (dp[end] != -1)
return dp[end];
int count = 0;
if (end >= one) {
count += dfs(end - one, zero, one);
}
if (end >= zero) {
count += dfs(end - zero, zero, one);
}
dp[end] = count % mod;
return dp[end];
}
public:
int countGoodStrings(int low, int high, int zero, int one) {
dp.resize(high + 1, -1);
dp[0] = 1;
// 유효한 길이 [low ~ high]의 문자열 수를 합산
int answer = 0;
for (int end = low; end <= high; ++end) {
answer += dfs(end, zero, one);
answer %= mod;
}
return answer;
}
};
GPT
이 코드는 재귀와 메모이제이션을 사용하여 “좋은 문자열”의 개수를 계산합니다. 각 문자열의 길이에 대해 가능한 모든 조합을 탐색하며, 이미 계산한 값을 메모이제이션하여 중복 계산을 방지합니다. 이 접근 방식은 효율적이며, 시간 복잡도를 가집니다.
문제 정의
-
주어진 조건:
- : “좋은 문자열”의 최소 길이.
- : “좋은 문자열”의 최대 길이.
- : 끝에 개의 을 추가 가능.
- : 끝에 개의 을 추가 가능.
-
목표:
- 길이가 인 “좋은 문자열”의 총 개수를 계산.
- 결과를 로 나눈 나머지를 반환.
코드 분석
1. 주요 아이디어
- 재귀와 메모이제이션:
dfs(end): 길이가 인 문자열의 개수를 계산.- 이미 계산된 값은
dp[end]에 저장하여 중복 계산 방지.
- 점화식:
- 길이가 인 문자열은 다음 두 가지 방법으로 생성 가능:
- : 길이의 문자열 뒤에 개의 추가.
- : 길이의 문자열 뒤에 개의 추가.
- 길이가 인 문자열은 다음 두 가지 방법으로 생성 가능:
2. 코드 단계별 설명
1. DP 배열 초기화
dp.resize(high + 1, -1);
dp[0] = 1;
dp[end]: 길이가 인 문자열의 개수를 저장.- : 길이가 인 문자열은 유일.
2. DFS 함수
int dfs(int end, int zero, int one) {
if (dp[end] != -1)
return dp[end];
int count = 0;
if (end >= one) {
count += dfs(end - one, zero, one);
}
if (end >= zero) {
count += dfs(end - zero, zero, one);
}
dp[end] = count % mod;
return dp[end];
}
-
기저 조건:
dp[end] != -1: 이미 계산된 값이 있으면 반환하여 중복 계산 방지.
-
점화식:
- : 호출.
- : 호출.
-
결과 저장:
- .
3. 유효 길이 합산
int answer = 0;
for (int end = low; end <= high; ++end) {
answer += dfs(end, zero, one);
answer %= mod;
}
- 길이가 인 모든 문자열의 개수를 합산.
- 연산으로 결과를 제한.
시간 및 공간 복잡도
시간 복잡도
- DFS 계산:
- 각 에 대해 한 번 계산 ().
- 결과 합산:
- 범위 합산 ().
총 시간 복잡도:
공간 복잡도
- DP 배열:
- .
- 재귀 호출 스택:
- 최대 깊이: .
총 공간 복잡도:
작동 예시
입력:
low = 3, high = 3, zero = 1, one = 2
계산 과정:
-
초기화:
-
DFS 호출:
- :
- .
- :
- .
- :
- .
- :
- 반환 .
- :
-
결과:
-
합산:
- .
출력:
3
확장 예시
입력:
low = 2, high = 4, zero = 1, one = 2
계산 과정:
-
초기화:
-
DFS 호출:
- , , .
-
결과:
-
합산:
- .
출력:
10