-
-
Notifications
You must be signed in to change notification settings - Fork 247
[jinvicky] WEEK05 solutions #1836
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
2308fe0
best time to buy and sell stock solution and 4 week solution comment …
ef08b1d
group anagrams solution
18bd398
fix lint
bb07450
implement trie prefix tree solution
27a0546
fix lint
1df0a9a
word break solution
2258086
work break comment added
1f95483
fix lint
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/** | ||
* 한글주석만 보고 코드를 작성해본다. | ||
* 조건문 안의 조건만 코드를 비우거나, 조건문만 남기고 안의 액션코드를 비우고 다시 작성해본다. | ||
* | ||
*/ | ||
class Solution { | ||
public int maxProfit(int[] prices) { | ||
/** | ||
max라는 메모이제이션 변수를 int로 선언한다. | ||
dp로 모든 경우의 수를 고려할 것이다. | ||
주식의 최소가격을 담은 변수를 int로 선언한다. 맨 처음에 prices[0] 값이 되면 좋겠다. | ||
*/ | ||
int max = 0; // dp memoization 변수 | ||
int min = prices[0]; // 주식 배열의 최소값 | ||
for (int i = 1; i < prices.length; i++) { | ||
/** | ||
현재 주식은 팔 때의 주식 가격을 나타낸다. | ||
max값은 (기존 최대이익, 최소주식을 현재 주식값에 팔았을 때의 이익) 중 더 큰 값으로 업데이트된다. | ||
현재 주식값이 기존 최소 주식값보다 작다면 현재 주식값으로 최솟값을 업데이트한다. | ||
*/ | ||
int currentMax = prices[i] - min; | ||
max = Math.max(max, currentMax); | ||
if (prices[i] < min) { | ||
min = prices[i]; | ||
} | ||
} | ||
|
||
return max; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,28 @@ | ||
import java.util.Arrays; | ||
|
||
|
||
// 왜 greedy가 아닐까? amount가 7이라고 가정했을 때 greedy라면 [1,3,4,5]에서 5를 우선시해서 5+1+1 총 3개를 사용할 것이지만, | ||
// 실제 정답은 3+4 로 총 2개가 된다. 그렇기에 단순히 욕심쟁이로 최댓값, 최솟값으로 접근하는 방식은 적합하지 않다. | ||
// greedy가 아니라면 보통 DP로 풀이한다. | ||
// DP의 기초인 1. Climbing Stairs 2. Best Time to Buy and Sell Stock 3. House Robber를 선행으로 풀고 접근했다. | ||
// DP의 기본은 i-1, i-2식으로 기존 값을 재사용하는 메모이제이션인데 나는 bottom-up으로 모든 dp를 풀이하려고 노력한다. (일관성) | ||
// DP는 값을 비교하기 위해서 Math.min(), Math.max()를 많이 사용하기에 초기값을 Integer.MAX_VALUE, Integer.MIN_VALUE로 염두했다. | ||
|
||
class Solution { | ||
public int coinChange(int[] coins, int amount) { | ||
int max=amount+1; | ||
int [] dp=new int[amount+1]; | ||
Arrays.fill(dp,max); | ||
dp[0]=0; | ||
for(int coin:coins){ | ||
for(int j=coin;j<=amount;j++){ // coin부터 시작해서 일반 루프보다 성능 향상 | ||
dp[j]=Math.min(dp[j],dp[j-coin]+1); | ||
int max = amount + 1; // 값 미표현이라면 Integer.MAX_VALUE가 더 직관적이지 않나? -> testcase에서 음수값 나와서 실패함 | ||
int[] dp = new int[amount + 1]; // 목표인 amount를 위한 공간 확보를 위해서 amount+1로 배열 사이즈를 측정 | ||
Arrays.fill(dp, max); // 최소 개수를 구하는 것이기 때문에 max값으로 채웠다. | ||
dp[0] = 0; // 첫 요소만 max가 아닌 0으로 설정한다. -> | ||
// 그냥 0부터 amount까지 이중 for문 하는 것보다 | ||
// j문에서 바깥 i의 코인값부터 인덱스로 시작하는 것이 같은 결과, 높은 성능. | ||
for (int coin : coins) { | ||
for (int j = coin; j <= amount; j++) { | ||
// dp[j - coin]: coin 동전을 하나 사용했을 때, 남은 금액 j - coin을 만드는 최소 동전 개수 | ||
// 코인값을 인덱스로서 계산해야 한다는 것을 몰랐음 j-coin에서 한참을 헤맨.... | ||
dp[j] = Math.min(dp[j], dp[j - coin] + 1); | ||
} | ||
} | ||
return dp[amount]>amount ? -1:dp[amount]; | ||
return dp[amount] > amount ? -1 : dp[amount]; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import java.util.*; | ||
import java.util.stream.Collectors; | ||
|
||
class Solution { | ||
/** | ||
* 41ms를 가진 낮은 성능의 첫번째 정답 코드 | ||
*/ | ||
public List<List<String>> groupAnagrams(String[] strs) { | ||
// 길이가 1이면 자체를 List로 감싸서 반환한다. | ||
if (strs.length == 1) { | ||
return List.of(List.of(strs[0])); | ||
} | ||
|
||
List<List<String>> groupList = new ArrayList<>(); | ||
/** | ||
* bf로 그룹핑을 할 수 있나? | ||
* strs를 for문으로 돌면서 "정렬한" 단어가 map에 있는 지 확인하고 존재할 경우 key로 조회한 list에 추가한다. | ||
* 마지막으로 map을 순회하면서 list들을 groupList.add(list); 한다. | ||
*/ | ||
Map<String, List<String>> map = new HashMap<>(); | ||
for (String s : strs) { | ||
String sortedS = Arrays.stream(s.split("")) | ||
.sorted() | ||
.collect(Collectors.joining()); | ||
List<String> v = map.get(sortedS); | ||
if (v == null) { | ||
map.put(sortedS, new ArrayList<>()); | ||
} | ||
map.get(sortedS).add(s); | ||
} | ||
|
||
for (List<String> list : map.values()) { | ||
groupList.add(list); | ||
} | ||
return groupList; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
/** | ||
* brute-force로 먼저 접근한 423ms의 최악의 성능 코드. | ||
*/ | ||
class Trie { | ||
|
||
private List<String> list; | ||
|
||
public Trie() { | ||
this.list = new ArrayList<>(); | ||
} | ||
|
||
public void insert(String word) { | ||
this.list.add(word); | ||
} | ||
|
||
public boolean search(String word) { | ||
for(String s : list) { | ||
if(s.equals(word)) return true; | ||
} | ||
return false; | ||
} | ||
|
||
public boolean startsWith(String prefix) { | ||
for(String s : list) { | ||
if(s.startsWith(prefix)) return true; | ||
} | ||
return false; | ||
} | ||
} | ||
|
||
/** | ||
* Your Trie object will be instantiated and called as such: | ||
* Trie obj = new Trie(); | ||
* obj.insert(word); | ||
* boolean param_2 = obj.search(word); | ||
* boolean param_3 = obj.startsWith(prefix); | ||
*/ |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import java.util.*; | ||
|
||
class Solution { | ||
public boolean wordBreak(String s, List<String> wordDict) { | ||
int n = s.length(); | ||
boolean[] dp = new boolean[n + 1]; // 빈 문자열을 대비해서 +1 길이로 설정 | ||
dp[0] = true; // 빈 문자열은 항상 가능 | ||
|
||
for (int i = 0; i < n; i++) { | ||
if (!dp[i]) continue; // 여기까지 못 오면 확장 불가 | ||
for (String w : wordDict) { | ||
int j = i + w.length(); | ||
if (j <= n && s.startsWith(w, i)) { | ||
dp[j] = true; | ||
} | ||
} | ||
} | ||
return dp[n]; | ||
} | ||
|
||
public boolean wordBreak2(String s, List<String> wordDict) { | ||
int n = s.length(); | ||
// List를 HashSet 객체 생성시 인자로 넣어 초기화가 가능합니다. | ||
// set은 List에서의 단어 탐색을 O(1) 성능으로 최적화하기 위해서 필요합니다. | ||
Set<String> wordSet = new HashSet<>(wordDict); | ||
|
||
// 빈 문자열일 경우를 대비해서 +1을 길이로 설정합니다. | ||
boolean[] dp = new boolean[n + 1]; | ||
// 빈 문자열을 항상 true이므로 0번째 dp[]에 true를 설정합니다. | ||
dp[0] = true; | ||
|
||
// 앞서 빈문자열을 셋팅했으니 i는 1부터 n까지 반복합니다. | ||
// j는 0부터 i보다 작을때까지 반복합니다. | ||
/** | ||
* j=0: s.substring(0, 1) = "l" | dp[0]=true | "l" in dict=false | ||
* ----- | ||
* j=0: s.substring(0, 2) = "le" | dp[0]=true | "le" in dict=false | ||
* j=1: s.substring(1, 2) = "e" | dp[1]=false | "e" in dict=false | ||
* ----- | ||
* j=0: s.substring(0, 3) = "lee" | dp[0]=true | "lee" in dict=false | ||
* j=1: s.substring(1, 3) = "ee" | dp[1]=false | "ee" in dict=false | ||
* j=2: s.substring(2, 3) = "e" | dp[2]=false | "e" in dict=false | ||
* ----- | ||
* j=0: s.substring(0, 4) = "leet" | dp[0]=true | "leet" in dict=true → dp[4] = true! | ||
* ----- | ||
* j=0: s.substring(0, 5) = "leetc" | dp[0]=true | "leetc" in dict=false | ||
* j=1: s.substring(1, 5) = "eetc" | dp[1]=false | "eetc" in dict=false | ||
* j=2: s.substring(2, 5) = "etc" | dp[2]=false | "etc" in dict=false | ||
* j=3: s.substring(3, 5) = "tc" | dp[3]=false | "tc" in dict=false | ||
* j=4: s.substring(4, 5) = "c" | dp[4]=true | "c" in dict=false | ||
* ----- | ||
* j=0: s.substring(0, 8) = "leetcode" | dp[0]=true | "leetcode" in dict=false | ||
* j=1: s.substring(1, 8) = "eetcode" | dp[1]=false | "eetcode" in dict=false | ||
* j=2: s.substring(2, 8) = "etcode" | dp[2]=false | "etcode" in dict=false | ||
* j=3: s.substring(3, 8) = "tcode" | dp[3]=false | "tcode" in dict=false | ||
* j=4: s.substring(4, 8) = "code" | dp[4]=true | "code" in dict=true → dp[8] = true! | ||
*/ | ||
for (int i = 1; i <= n; i++) { | ||
for (int j = 0; j < i; j++) { | ||
// 예시를 보면 (start, end)에서 start가 증가할 동안 end는 고정됩니다. 따라서 start=j, end=i가 되어야 합니다. | ||
if (dp[j] && wordSet.contains(s.substring(j, i))) { | ||
dp[i] = true; | ||
break; | ||
} | ||
} | ||
} | ||
return dp[n]; | ||
} | ||
} |
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
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
groupList 변수 필요 없이 return new ArrayList<>(map.values()) 이런식으로도 가능하지는 않을까요?
그리고 groupList를 사용하는 곳 근처에 선언부가 있으면 좋을 것 같습니다. 선언하는 라인과 사용하는 라인 사이에 for loop이 있다보니 거기서 groupList를 사용하는 것처럼 보여서 다시 확인하게 되어서요.