Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
name: 민정 PR 템플릿
about: '알고리즘 '
목표 문제 수: 3개
목표 유형: DP
-> 푼 문제
아래는 제가 정리한 내용 중에서, 핵심이 되는 플로우와 TIL 위주를 가져왔습니다.
PGS ##짝지어 제거하기: 스택/큐 Level 2
정리한 노션 링크: 노션
🔍Intuition
짝을 찾아야 한다? 그러면 스택이 답이다.그래서 이 문제는 스택이겠구나 싶었다.
(하지만 처음 접근할 때는 맨날 DP풀다가 오랜만에 스택 문제를 접해서, 다른 길로 샜다…)(그래서 다른 길로 세서 잘못 시간초과가 나왔던 코드와, 스택으로 접근한 코드 모두 기록했다.)스택으로 접근하려면 2가지를 고려해야 한다.
언제 push할 것인가?
⇒ pop하지 않을 경우에는 모두 추가한다.
또는 stack에 아무것도 없다면 추가한다. (왜냐하면, 초기에 아무것도 없는데 pop해버리면 indexError가 발생하기 때문에 stack이 비어있을 경우에 추가하는 조건문을 넣어둬야 한다)
언제 pop할 것인가?
⇒ 이건 쉽다. stack의 top과 현재위치에 해당하는 문자가 같으면 pop한다.
여기서 하나 더 고려해야 한다. 언제 반복을 종료할것인가?
⇒ 주어진 문자열
s를 다 보고 나면 종료해야 한다. 즉, for문을 쓰면 된다.🚩플로우
접근: 스택
첫 문자를 stack에 push(
append)한다.stack이 비어 있을 경우 → 문자를 push(
append)한다. (스택이 비어있을 경우, pop하면 IndexError 발생)stack에 있는 top의 값과 현재 값(
c)과 일치하다면 → stack의 top을 pop한다.→ 그게 아닐 경우, stack에 다시 push(
append)한다.모두 다 짝을 찾아서 stack이 비어있다면 →
return 1을, 비어있지 않다면 →return 0을 한다.🚩My submission
💡TIL
백준 #11055. 가장 큰 증가하는 부분수열: DP 실버2
정리한 노션 링크: 노션
🔍Intuition
지난번 [#11053. 가장 긴 증가하는 부분수열](https://www.notion.so/11053-f300eb3a4ac740e09549cdcee0187492?pvs=21) 문제의 시리즈 문제에 접근해보려고 한다. 지난번 #11053다음 단계인 #11055번. 가장 큰 증가하는 부분 수열의 문제는 아래와 같다.
처음에는 오잉 가장 큰 수열하려면 전부 다 더하면 되지 않을까?! 했는데, 그게 아니었다.
조건은 2가지인것.
이전에 #11053은 DP 테이블에 가장 “긴” 증가하는 수열의 길이를 저장하는 반면에, 이번 #11055 에서는 DP테이블에 증가하는 수열 중에서 가장 합이 “큰” 수열의 합이 저장되어야 한다. -
따라서 증가하는 수열의 코드를 기반으로 한다.(놀랍게도 일주일전에 풀었는데 기억 안 남;;😓)
🚩플로우
이 방식으로 접근할 경우 dp에는 아래와 같이 저장되게 된다.(예시 기준)
nums[i] > nums[j]라면 ⇒ 기존의dp[i]와 새로 더해져 구해지는dp[j] + nums[i]중 큰 값을 d[i]로 갱신한다.nums[i] <= nums[j라면, 기존의dp[i]와nums[i]중 큰 값으로 갱신하면 된다.🚩My submission
50분 남을 때까지 계속 시도했는데 ‘틀렸습니다’가 계속 나와서 다양한 dp점화식을 시도해보았으나 되지 않았다.. 결국 힌트를 보고 최종 답안을 제출하게 되었다.
코드로 확인해보니까 dp에 처음 값은 1로 둬야하고, dp[0]의 값만 따로 초기화해줘야 한다.
그리고 이렇게 해줄 경우, nums[j]가 nums[i]보다 작은 경우(
else) 도 처리를 해주어야 한다. (난 이 부분에 대한 처리를 해주지 않았다..)→ else인 경우에는 dp에 있는 값 혹은 자기 자신의 값을 대입해주면 된다.
(개빡친다……………. 나 자신한테)
💡TIL
처음엔 dp를 초기화할 때
dp = nums로 했다.그랬더니 파이썬의 포인터 기능이 적용이 되었는지, 자꾸 dp에 저장한 값이 nums에 연동되는 문제가 발생했다. 그래서 dp를 별도로 선언하고, nums의 값들을 for문을 통해 복사해주니 이 문제가 해결되었다.
dp에서는 보여지는 이외로 전혀 부분수열이 만들어지지 않을 경우도 고려해야 한다. 처음에 일차적으로 짰던 점화식
dp[i] += nums[j]이 전혀 수행되지 않을 수도 있다는 뜻이다. 그렇게 되면 dp에는 초기값만 남게 되고 가장 큰 값을 구하지 못하게 된다.위에 점을 반영했음에도 틀려쓴데 그 이유는 if의 반례인
else인 경우를 생각하지 않아서였다.⇒ 아래와 같이 짜는 이유는 극단적으로 해당 인덱스에서 증가하는 부분수열이 전혀 만들어지지 않을 경우, 뒤의 과정의 수행을 위해 현재값(nums[i])이라도 할당해주어야 하기 때문이다.
즉, 뒤의 과정에서 해당 인덱스부터 시작하는 부분 수열을 고려해주어야 한다는 뜻이다.
백준 #9251. LCS: DP 골드5
정리한 노션 링크: 노션
🔍Intuition
아래는 굉장히 잘 정리해주신 블로거분의 개념정리 게시글이다.
LCS에 대한 개념을 알아야 문제를 풀 수 있기 때문에 제한시간 1시간 내에 개념에 대한 이해를 먼저 하고 시작했다.
[[알고리즘] 그림으로 알아보는 LCS 알고리즘 - Longest Common Substring와 Longest Common Subsequence](https://velog.io/@emplam27/알고리즘-그림으로-알아보는-LCS-알고리즘-Longest-Common-Substring와-Longest-Common-Subsequence)
(표를 만들고 싶었지만 나도 시험기간인지라 이해만 하고 넘어감)
점화식
최장 공통 부분수열의 점화식을 코드로 작성해보았습니다. 위와 마찬가지로 LCS라는 2차원 배열에 매칭하고 마진값을 설정한 후 검사한다.
LCS[i - 1][j]와LCS[i][j - 1]중에 큰값을 표시한다.+1하기 위해LCS[i - 1][j - 1]값을 찾아+1한다.🚩나의 제출 과정 코드 기록
sys.stdin.readline를 사용하면, 개행문자\n이 포함된다. 문자열에 대해서만 처리를 하려면strip()함수를 사용하여 개행문자는 제거해줘야 한다.⇒ 제거해주었더니 개행문자는 출력되지 않았다. 하지만 답이 다르게 나온다. 이 점 때문에 틀리다고 나왔던 것이다.
그렇다면 왜 틀린걸까?? 다시 내 코드를 보면,
⇒
i = 0이거나j = 0으로 두기 위해 일부러 반복문을 1부터 시작했다. 그리고 이때의i = 0또는j = 0부분은 마진에 대한 부분으로,str_A나str_B가 시작하는 부분이 아니다.이 말은 즉슨,
str_A나str_B가 시작하는 부분은 인덱스 1부터이고 이를 구현하려면 배열의 크기를 1씩 더 키워야 한다는 의미이다.🚩최종 답안
💡TIL
sys.stdin.readline를 사용하면, 엔터(개행 문자\n)도 입력으로 받아들인다. 이는 **str_A**와 **str_B**가 예상과 달리 개행 문자를 포함하게 될 수 있음을 의미한다. 이를 제거하기 위해strip()함수를 사용하여 문자열의 양쪽 끝에서 개행 문자를 제거해야 한다.일부러 마진은 둔다⇒ 이 말은 즉슨,i=0이거나j=0인 경우,0으로 두어야 하고, 이 부분을 제외하고 저장을 시작해야 하기 때문에 배열의 크기를 1씩 더 키워야 한다. 또한,str_A나str_B가 시작하는 부분은 인덱스 1부터이고 이를 구현하려면 배열의 크기를 1씩 더 키워야 한다는 의미이다.