leetcode 1143. 가장 긴 공통 부분 시퀀스
주제 링크: 1143. 가장 긴 공통 부분 수열 - LeetCode
비디오 링크: 동적 프로그래밍 부분 수열 문제의 고전적인 주제 | LeetCode: 1143. 가장 긴 공통 부분 수열_哔哩哔哩_bilibili
주제 개요
두 문자열 text1과 text2가 주어지면 이 두 문자열의 가장 긴 공통 부분 수열의 길이를 반환합니다.
문자열의 하위 시퀀스는 이러한 새 문자열을 참조합니다. 즉, 문자의 상대적 순서를 변경하지 않고 원래 문자열에서 일부 문자를 삭제(또는 문자를 삭제하지 않음)하여 형성된 새 문자열입니다.
예를 들어, "ace"는 "abcde"의 하위 시퀀스이지만 "aec"는 "abcde"의 하위 시퀀스가 아닙니다. 두 문자열의 "공통 하위 시퀀스"는 두 문자열이 공통으로 갖는 하위 시퀀스입니다.
두 문자열에 공통 하위 시퀀스가 없으면 0을 반환합니다.
예시 1:
입력: text1 = "abcde", text2 = "ace"
출력: 3
설명: 가장 긴 공통 부분 수열은 길이가 3인 "ace"입니다.
예 2:
입력: text1 = "abc", text2 = "abc"
출력: 3
설명: 가장 긴 공통 부분 수열은 "abc"이고 길이는 3입니다.
예시 3:
입력: text1 = "abc", text2 = "def"
출력: 0
설명: 두 문자열에 공통 하위 시퀀스가 없습니다. 0을 반환합니다.
생각의 기차
1. dp 배열의 의미를 결정합니다.
dp[i][j]: 길이가 [0, i - 1]인 문자열 text1과 길이가 [0, j - 1]인 문자열 text2의 가장 긴 공통 부분 수열은 dp[i][j]입니다. 이 정의는 다음 코드의 구현을 보다 편리하게 만들기 위한 것입니다)
2. 재귀 공식 결정
dp[i][j] = dp[i - 1][j - 1] + 1 (조건: text1[i - 1]이 text2[j - 1]과 같음)
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) (조건: text1[i - 1]은 text2[j - 1]과 동일하지 않음)
3. 어레이 초기화
dp[i][0] = 0,dp[0][j] = 0
4. 순회 순서 결정
위 그림을 보면 dp[i][j]는 왼쪽, 위쪽, 왼쪽 위쪽으로 도출할 수 있으므로 위에서 아래로, 왼쪽에서 오른쪽으로 순서가 있음을 알 수 있다.
5. 배열 인쇄
암호
lass Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
vector<vector<int>> dp(text1.size() + 1,vector<int>(text2.size() + 1,0));
for(int i = 1;i <= text1.size();i++) {
for(int j = 1;j <= text2.size();j++) {
if(text1[i - 1] == text2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else {
dp[i][j] = max(dp[i - 1][j],dp[i][j - 1]);
}
}
}
return dp[text1.size()][text2.size()];
}
};
leetcode 1035. 분리된 라인
주제 링크: 1035. 분리된 줄 - LeetCode
영상 링크: 동적 프로그래밍의 하위 수열 문제, 약을 바꾸지 않고 수프를 바꾸다 | LeetCode: 1035. Disjoint Lines_哔哩哔哩_bilibili
주제 개요
두 개의 별도 수평선에 주어진 순서대로 nums1
정수 를 쓰십시오 nums2
.
nums1[i]和nums2[j]
이제 두 숫자를 모두 만족시켜야 하는 두 숫자를 연결하는 선을 그릴 수 있습니다 .
-
nums1[i] == nums2[j]
- 그리고 그려진 선은 다른 선(비수평선)과 교차하지 않습니다.
선은 끝점에서도 교차할 수 없습니다. 각 번호는 하나의 선에만 속할 수 있습니다.
이런 방식으로 선을 그리고 그릴 수 있는 최대 선 수를 반환합니다.
예시 1:
입력: nums1 = [1,4,2], nums2 = [1,2,4]
출력: 2
설명: 위 그림과 같이 교차하지 않는 두 개의 선을 그릴 수 있습니다.
그러나 nums1[1]=4에서 nums2[2]=4까지의 선이 nums1[2]=2에서 nums2[1]=2까지의 선과 교차하기 때문에 세 번째 분리된 선을 그릴 수 없습니다.
예 2:
입력: nums1 = [2,5,1,2,5], nums2 = [10,5,2,1,5,2]
출력: 3
생각의 기차
사실 이 질문의 본질은 이전 질문인데 이전 질문의 설명이 변경되었고 심지어 코드도 변경되지 않았지만 이름이 변경되었습니다. 이 질문은 그려진 연결의 최대 수를 구하는 것이지만 실제로는 두 문자열의 가장 긴 공통 부분 수열의 길이를 구하는 것입니다!
암호
class Solution {
public:
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
vector<vector<int>> dp(nums1.size() + 1,vector<int>(nums2.size() + 1,0));
for(int i = 1;i <= nums1.size();i++) {
for(int j = 1;j <= nums2.size();j++) {
if(nums1[i - 1] == nums2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else {
dp[i][j] = max(dp[i][j - 1],dp[i - 1][j]);
}
}
}
return dp[nums1.size()][nums2.size()];
}
};
leetcode 53. 최대 하위 시퀀스 합계
항목 링크: 53. 최대 하위 배열 합계 - LeetCode
영상 링크: 복잡해 보이지만 사실은 단순한 동적 프로그래밍 | LeetCode: 53. 최대 부분 수열 sum_哔哩哔哩_bilibili
주제 개요
정수 배열 nums가 주어지면 최대 합계를 갖는 연속 하위 배열(하위 배열에는 최소한 하나의 요소가 포함되어 있음)을 찾고 최대 합계를 반환합니다.
예:
입력: [-2,1,-3,4,-1,2,1,-5,4]
출력: 6
설명: 연속된 하위 배열 [4,-1,2,1]의 합이 가장 큰 값인 6입니다.
생각의 기차
이 질문은 이전에 탐욕스럽게 이루어졌습니다!
이제 모션 규칙을 사용하여 다시 수행해 보세요.
1. dp 배열의 의미를 결정합니다.
dp[i]: nums[i](첨자 i 포함)로 끝나는 최대 연속 부분 수열의 합은 dp[i]입니다.
2. 재귀 공식 결정
dp[i - 1] + nums[i] (이전 하위 수열의 합을 계속 계산함)
nums[i] (이전 연속 하위 수열을 합하지 말고 계산을 다시 시작하세요)
所以dp[i] = max(dp[i - 1] + nums[i], nums[i]);
3. 어레이 초기화
dp[0] = 숫자[0]
4. 순회 순서 결정
앞에서 뒤까지
5. 배열 인쇄
암호
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size() == 0) return 0;
vector<int> dp(nums.size());
dp[0] = nums[0];
int result = dp[0];
for(int i = 1;i < nums.size();i++) {
dp[i] = max(dp[i - 1] + nums[i],nums[i]);
if(dp[i] > result) result = dp[i];
}
return result;
}
};