10주차 일요일 1 - LeetCode-Study-Team/solutions GitHub Wiki
-
특징
- O(N)으로 끝내자
- 사각형의 bottom right로 가정
- 방식: Min(같은행 전열, 전행 같은열, 전행 전열)
- 의미적으로, 사각형 개수 (or 제일 큰 정사각형 한변 길이)
- 0행이나 0열은 그대로 두기
- 사각형의 bottom right로 가정
- O(N)으로 끝내자
-
{0, 1, 1, 1} {1, 1, 1, 1} {0, 1, 1, 1} // Final Matrix 값 {0, 1, 1, 1} {1, 1, 2, 2} {0, 1, 2, 3}
public int countSquares(int[][] A) {
int res = 0;
for (int row = 0; row < A.length; ++row) {
for (int col = 0; col < A[0].length; ++col) {
if (A[row][col] > 0 && row > 0 && col > 0) { // 0행이나 0열은 그대로 두기
A[row][col] = Math.min(A[row - 1][col - 1], Math.min(A[row - 1][col], A[row][col - 1])) + 1;
}
res += A[row][col];
}
}
return res;
}
-
특징
- Input:
{ "bdca", "a", "b", "bca", "ba", "bda"};
- 최대 체인: "a", "ba", "bda", "bdca"
- 풀이
- bdca 의 가능한 chain을 찾아
- 예, dca bca bdc
- bdca 의 가능한 chain을 찾아
- Input:
-
Map 결과값
-
{a=1, ab=2, bd=1, abd=3, ac=2, abc=3, abdd=4}
-
class Solution {
public int longestStrChain(String[] words) {
Map<String, Integer> dp = new HashMap<>();
Arrays.sort(words, (a, b) -> a.length() - b.length());
int longestWordSequenceLength = 1;
for (String word : words) {
int presentLength = 1;
// letter 하나씩 제거하며 가능한 모든 단어 찾기
for (int i = 0; i < word.length(); i++) {
StringBuilder sb = new StringBuilder(word);
sb.deleteCharAt(i);
int previousLength = dp.getOrDefault(sb.toString(), 0);
presentLength = Math.max(presentLength, previousLength + 1);
}
dp.put(word, presentLength);
longestWordSequenceLength = Math.max(longestWordSequenceLength, presentLength);
}
return longestWordSequenceLength;
}
}
['abcd','abc','bcd','abd','ab','ad','b']
public int longestStrChain(String[] words) {
Map<String, Integer> memo = new HashMap<>();
Set<String> wordsPresent = new HashSet<>();
Collections.addAll(wordsPresent, words);
int ans = 0;
for (String word : words) {
ans = Math.max(ans, dfs(wordsPresent, memo, word));
}
return ans;
}
private int dfs(Set<String> wordSet, Map<String, Integer> memo, String currentWord) {
// DP 장점 활용: 최대 체인값 map에서 찾아오기
if (memo.containsKey(currentWord)) {
return memo.get(currentWord);
}
int maxLength = 1; // 현재 단어의 최대 chain
StringBuilder sb = new StringBuilder(currentWord);
// 가능한 모든 chain string 만들기
for (int i = 0; i < currentWord.length(); i++) {
sb.deleteCharAt(i);
String newWord = sb.toString();
// 주어진 단어 set 중 하나면, 다시 그 단어의 최대 체인 가져오기 위해 DFS
if (wordSet.contains(newWord)) {
maxLength = Math.max(maxLength, 1 + dfs(wordSet, memo, newWord));
}
sb.insert(i, currentWord.charAt(i));
}
memo.put(currentWord, maxLength);
return maxLength;
}
[ "a", "b" ,"ba", "bca", "bda", "bdca" ]
class Solution {
public int longestStrChain(String[] words) {
Arrays.sort(words, ((o1, o2) -> o1.length() - o2.length()));
int[] dp = new int[words.length];
dp[0] = 1;
helper(words, dp, 0);
return IntStream.of(dp).max().orElse(0);
}
private void helper(String[] words, int[] dp, int start) {
if (start >= words.length) return;
dp[start] = Math.max(1, dp[start]);
for (int i = start; i < words.length; i++) {
// 추가하기: if words[i].length > words[start].lenght stop exploration
if (isChain(words[start], words[i])) {
dp[i] = Math.max(dp[start] + 1, dp[i]);
}
}
helper(words, dp, start + 1);
}
private boolean isChain(String left, String right) {
if (left.length() < right.length() - 1 || left.length() == right.length()) return false;
int i = 0;
int mismatchCount = 0;
for (char rightC : right.toCharArray()) {
if (i == left.length()) return true;
if (rightC == left.charAt(i)) {
i++;
continue;
}
mismatchCount++;
if (mismatchCount >= 2) { // 2개 이상 다르면 chain 아님
return false;
}
}
return true;
}
}