1. 알고리즘 문제 해결
LCS 2(백준 9252):
오랜만에 따로 알고리즘 문제를 풀었다. 캠프의 루틴에 따라 매일 매일 프로그래머스의 알고리즘 문제를 하나씩 풀고있긴 하지만, 결이 좀 다르다. 제시된 문제들이 비교적 간단하고, 백준 문제들처럼 입력과 출력, 제한 시간 및 메모리 등이 확실하게 주어지지 않는 문제도 많아서 알고리즘 사고를 연습하기 보다는 코틀린에 더 익숙해지는 용도로 쓰고 있다.
한동안 팀 프로젝트를 진행하느라, 개인적으로 이렇게 알고리즘 문제를 풀지 못했는데 오랜만에 푸니까 더 재밌게 느껴지는 것 같다.
이 문제는 알고리즘 과목을 수강하면 DP를 배우면서 한번쯤은 공부하는 문제가 아닐까 생각한다. 브루트 포스로 해결하자면 각각의 문자열의 길이가 n과 m이라고 했을 때, 시간복잡도가 O(n * 2^m)에 달할 것이다. 대강 생각해본거라 확실하지는 않지만, 한 문자열에 대해 모든 부분 수열을 만들어 보려면 O(2^n)만큼 걸릴 것이고 또 그걸 다른 문자열과 선형탐색으로 매번 비교해봐야 하니 맞을 것이다.
여튼 수업 때 다루기도 하고, 이미 너무나도 잘 알려진 알고리즘 문제이기도 하다. 그 로직도 심플하다.
- 어떤 두 문자열 X, Y의 끝 문자가 같다면, 두 문자열의 LCS의 끝 문자도 당연히 같을 것이다. 그리고 X의 끝 문자와 Y의 끝 문자를 떼고 새로운 LCS를 생각할 수 있다.
- 만약 다르다면, 새로운 LCS는 X의 끝 문자를 뗀 경우와 Y의 끝 문자를 뗀 경우로 다시 생각해볼 수 있을 것이다.
- 최장 공통 부분 수열이므로, 당연히 두 선택지 중 더 긴 LCS를 만들 수 있는 쪽을 선택해야 한다.
- 끝 문자를 떼내다가 어떤 문자열의 길이가 0이 된다면 LCS 그 때의 LCS 길이는 0일 수밖에 없다.
- 이걸 점화식으로 만들면 아래와 같이 될 것이다.
- 식을 훑어봐도 알 수 있고, 개념을 그려봐도 알 수 있듯이 2차원 배열을 통해서 각 상태의 LCS 길이를 저장해둔다면 재사용해서 O(nm)만에 LCS 길이를 찾아낼 수 있을 것이다.
이 로직을 간단하게 구현했고, 실제 LCS에 해당하는 문자열은 되추적을 통해 알아냈다. 되추적을 하는 방법은 너무 당연하지만, dp 배열의 가장 끝(dp[n][m])에 있는 값으로부터, 해당 값이 올 수 있던 경로를 반대로 찾아가면 된다. 되추적 과정에서 두 끝 문자가 일치하는 경우에 해당 문자를 LCS 문자열에 담아뒀다가 마지막에 출력해주면 끝이다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
string s1, s2;
cin >> s1 >> s2;
vector<vector<int> > dp(s1.size()+1, vector<int>(s2.size()+1, 0));
for(int i=1; i<=s1.size(); i++) {
for(int j=1; j<=s2.size(); j++) {
dp[i][j] = (s1[i-1]==s2[j-1] ? dp[i-1][j-1]+1 : max(dp[i-1][j], dp[i][j-1]));
}
}
int i = s1.size();
int j = s2.size();
vector<char> revLcs;
while(i>0 && j>0) {
if(s1[i-1]==s2[j-1]) {
revLcs.push_back(s1[i-1]);
i--;
j--;
}else {
if(dp[i-1][j]>dp[i][j-1]) {
i--;
}else {
j--;
}
}
}
cout << dp[s1.size()][s2.size()] << "\n";
for(int k=revLcs.size()-1; k>=0; k--) {
cout << revLcs[k];
}
}
2. 앱개발 숙련 주차
오늘부로 이제 새로운 주차인 앱개발 숙련 주차에 진입했다.
ViewBinding이나 RecyclerView, Fragment 등 안드로이드 구현의 기본기를 배우는 주차인듯 했다. 인트로에 적힌 CRUD 때문에 통신이나 DB작업도 다루게 되나 했는데 훑어보니 그건 아닌 것 같았다.
전반적으로 어려운 내용은 없는 것 같다. 개인 과제도 확인했는데 이번에도 무리 없이 구현할 수 있는 내용들이었다. 확인하면서 구조는 머리 속에 다 그렸으니, 그리 오래 걸리진 않을 것 같다.
오늘은 지급된 강의를 반절정도 들었는데, ViewBinding의 사용과 다양한 AdapterView들에 대해 설명하고 있었다. 실상 쓰는건, RecyclerView에 ListAdapter 쓰는 형태가 제일 많았던 거 같은데 GridAdapter 등은 처음 보는 개념이었다. 그래서 내가 예전에 학습하면서 놓친 부분이 있나 했는데, 아니나 다를까 강의에서도 실무에서 대부분 RecyclerView를 사용한다고 언급해서 안심했다.
그래도 알고 있던 내용이라도 다시보고, 조금이라도 더 나아갈 수 있게 노력해야겠다. 챌린지반 공부도 진행하고, 사이드 프로젝트도 진행하는 것과 함께.
'내일배움캠프 안드로이드 3기' 카테고리의 다른 글
[TIL] 24.04.15 알고리즘, 앱개발 숙련 주차 개인과제 (0) | 2024.04.15 |
---|---|
[TIL] 24.04.11 알고리즘, 개인 과제 Dialog 에러 (0) | 2024.04.11 |
[TIL] 24.04.08 팀 프로젝트 회고 (0) | 2024.04.08 |
[TIL] 24.04.04 팀 프로젝트, 챌린지반 과제 (0) | 2024.04.04 |
[TIL] 24.04.03 팀 프로젝트 (1) | 2024.04.03 |