-
Notifications
You must be signed in to change notification settings - Fork 0
276. Paint Fence #33
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
Open
Ryotaro25
wants to merge
4
commits into
main
Choose a base branch
from
problem30
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
276. Paint Fence #33
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
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,97 @@ | ||
class Node { | ||
public: | ||
int key; | ||
int value; | ||
Node* prev; | ||
Node* next; | ||
Node(int k, int v) : key(k), value(v), prev(nullptr), next(nullptr) {} | ||
}; | ||
|
||
class MyLRUCache { | ||
public: | ||
MyLRUCache(int size) : limit(size), size(0) { | ||
sentinel = new Node(-1, -1); | ||
sentinel->next = sentinel; | ||
sentinel->prev = sentinel; | ||
} | ||
|
||
~MyLRUCache() { | ||
delete sentinel; | ||
} | ||
|
||
int Get(int key) { | ||
if (cache.find(key) == cache.end()) { | ||
return -1; | ||
} | ||
Node* node = cache[key]; | ||
int value = node->value; | ||
Remove(key); | ||
Put(key, value); | ||
return value; | ||
} | ||
|
||
void Put(int key, int value) { | ||
if (cache.find(key) != cache.end()) { | ||
Remove(key); | ||
} | ||
Node* node = new Node(key, value); | ||
Node* head = sentinel->next; | ||
sentinel->next = node; | ||
node->next = head; | ||
head->prev = node; | ||
node->prev = sentinel; | ||
cache[key] = node; | ||
size++; | ||
if (size > limit) { | ||
Remove(sentinel->prev->key); | ||
} | ||
} | ||
|
||
private: | ||
// 今回はhashなので | ||
unordered_map<int, Node*> cache; | ||
int limit; | ||
int size; | ||
Node* sentinel; | ||
|
||
void Remove(int key) { | ||
Node* node = cache[key]; | ||
node->prev->next = node->next; | ||
node->next->prev = node->prev; | ||
cache.erase(key); | ||
delete node; | ||
size--; | ||
} | ||
}; | ||
|
||
class Solution { | ||
public: | ||
int numWays(int num_posts, int num_colors) { | ||
MyLRUCache cache(1000); | ||
cache.Put(1, num_colors); | ||
cache.Put(2, num_colors * num_colors); | ||
|
||
return CountNumWays(num_posts, num_colors, cache); | ||
} | ||
|
||
private: | ||
int CountNumWays(int num_posts, int num_colors, MyLRUCache& cache) { | ||
if (num_posts == 1) { | ||
return num_colors; | ||
} | ||
if (num_posts == 2) { | ||
return num_colors * num_colors; | ||
} | ||
|
||
int colors_ways = cache.Get(num_posts); | ||
if (colors_ways != -1) { | ||
return colors_ways; | ||
} | ||
|
||
int same_pattern_ways = CountNumWays(num_posts - 2, num_colors, cache); | ||
int different_pattern_ways = CountNumWays(num_posts - 1, num_colors, cache); | ||
colors_ways = (num_colors - 1) * (same_pattern_ways + different_pattern_ways); | ||
cache.Put(num_posts, colors_ways); | ||
return colors_ways; | ||
} | ||
}; |
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,97 @@ | ||
class Node { | ||
public: | ||
int key; | ||
int value; | ||
Node* prev; | ||
Node* next; | ||
Node(int k, int v) : key(k), value(v), prev(nullptr), next(nullptr) {} | ||
}; | ||
|
||
class MyLRUCache { | ||
public: | ||
MyLRUCache(int size) : limit(size), size(0) { | ||
sentinel = new Node(-1, -1); | ||
sentinel->next = sentinel; | ||
sentinel->prev = sentinel; | ||
} | ||
|
||
~MyLRUCache() { | ||
delete sentinel; | ||
} | ||
|
||
int Get(int key) { | ||
if (cache.find(key) == cache.end()) { | ||
return -1; | ||
} | ||
Node* node = cache[key]; | ||
int value = node->value; | ||
Remove(key); | ||
Put(key, value); | ||
return value; | ||
} | ||
|
||
void Put(int key, int value) { | ||
if (cache.find(key) != cache.end()) { | ||
Remove(key); | ||
} | ||
Node* node = new Node(key, value); | ||
Node* head = sentinel->next; | ||
sentinel->next = node; | ||
node->next = head; | ||
head->prev = node; | ||
node->prev = sentinel; | ||
cache[key] = node; | ||
size++; | ||
if (size > limit) { | ||
Remove(sentinel->prev->key); | ||
} | ||
} | ||
|
||
private: | ||
// 今回はhashなので | ||
unordered_map<int, Node*> cache; | ||
int limit; | ||
int size; | ||
Node* sentinel; | ||
|
||
void Remove(int key) { | ||
Node* node = cache[key]; | ||
node->prev->next = node->next; | ||
node->next->prev = node->prev; | ||
cache.erase(key); | ||
delete node; | ||
size--; | ||
} | ||
}; | ||
|
||
class Solution { | ||
public: | ||
int numWays(int num_posts, int num_colors) { | ||
MyLRUCache cache(1000); | ||
cache.Put(1, num_colors); | ||
cache.Put(2, num_colors * num_colors); | ||
|
||
return CountNumWays(num_posts, num_colors, cache); | ||
} | ||
|
||
private: | ||
int CountNumWays(int num_posts, int num_colors, MyLRUCache& cache) { | ||
if (num_posts == 1) { | ||
return num_colors; | ||
} | ||
if (num_posts == 2) { | ||
return num_colors * num_colors; | ||
} | ||
|
||
int colors_ways = cache.Get(num_posts); | ||
if (colors_ways != -1) { | ||
return colors_ways; | ||
} | ||
|
||
int same_pattern_ways = CountNumWays(num_posts - 2, num_colors, cache); | ||
int different_pattern_ways = CountNumWays(num_posts - 1, num_colors, cache); | ||
colors_ways = (num_colors - 1) * (same_pattern_ways + different_pattern_ways); | ||
cache.Put(num_posts, colors_ways); | ||
return colors_ways; | ||
} | ||
}; |
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,23 @@ | ||
class Solution { | ||
public: | ||
int numWays(int n, int k) { | ||
if (n == 0) { | ||
return 0; | ||
} | ||
if (n == 1) { | ||
return k; | ||
} | ||
if (n == 2) { | ||
return k * k; | ||
} | ||
vector<int> paint_ways_so_far(n + 1); | ||
paint_ways_so_far[1] = k; | ||
paint_ways_so_far[2] = k * k; | ||
for (int i = 3; i <= n; i++) { | ||
int same_paint = paint_ways_so_far[i - 2] * (k - 1); | ||
int diff_paint = paint_ways_so_far[i - 1] * (k - 1); | ||
paint_ways_so_far[i] = same_paint + diff_paint; | ||
} | ||
return paint_ways_so_far.back(); | ||
} | ||
}; |
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,24 @@ | ||
class Solution { | ||
public: | ||
int numWays(int n, int k) { | ||
if (n == 0) { | ||
return 0; | ||
} | ||
if (n == 1) { | ||
return k; | ||
} | ||
if (n == 2) { | ||
return k * k; | ||
} | ||
int two_previous_way = k; | ||
int one_previous_way = k * k; | ||
for (int i = 2; i < n; i++) { | ||
int same_paint = two_previous_way * (k - 1); | ||
int diff_paint = one_previous_way * (k - 1); | ||
|
||
two_previous_way = one_previous_way; | ||
one_previous_way = same_paint + diff_paint; | ||
} | ||
return one_previous_way; | ||
} | ||
}; |
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,72 @@ | ||
## ステップ1 | ||
色のパターンはkもしくはk-1 | ||
>There cannot be three or more consecutive posts with the same color. | ||
なので、同じ色が2色まではkそれ以外はk-1種類 | ||
postsの数が0色、1色や2色の場合もあるので考慮する | ||
3色目以降は、1つ前と2つ前の状態を考慮して色を選ぶ必要がある | ||
|
||
時間 | ||
O(n) | ||
|
||
空間 | ||
O(1) | ||
|
||
## ステップ2 | ||
・変数名変更 | ||
waysをつけることで明示的に方法(複数形)があると伝える | ||
|
||
・2つ前、1つ前のの情報を保持するのにvectorを使う必要はない | ||
past_two_colors_waysの要素は2つなのでvectorに入れる必要はない | ||
|
||
・0の場合の特別処理を削除 | ||
回答に使っているnum_waysを0で初期化しているため | ||
|
||
## 他の解法 | ||
__・フィボナッチ数列を使うことで時間計算量 O(log n)で解くことができる__ | ||
参照 : https://github.com/TORUS0818/leetcode/pull/32/commits/50d9a5f46afbe969f08a116f412232e540ca159d | ||
参照 :https://github.com/goto-untrapped/Arai60/pull/44/commits/b0b76df73f7b0b3c15b5ae4aef0066cfe611eb1b | ||
|
||
__・DPに、bottom-upとtop-downの2種類が存在する__ | ||
アルゴリズムイントロダクション第二巻に乗っているので関連する章を読む(8/30) | ||
参照 : https://github.com/TORUS0818/leetcode/pull/32/commits/50d9a5f46afbe969f08a116f412232e540ca159d | ||
|
||
以下アルゴリズムイントロダクション第二巻を読んで追記(8/31) | ||
*トップダウン式* | ||
さっくりとした理解 | ||
nこの要素があったとしてn-1、n-2...と範囲を狭めながら再帰的に部分問題を処理する方式 | ||
top_down.cppにて実装。 | ||
ループの中で、直前2つが同じ色をしているものと異なる色を再帰的に呼び出している | ||
時間 | ||
O(n) | ||
|
||
空間 | ||
O(n) | ||
|
||
*ボトムアップ式* | ||
ざっくりとした理解 | ||
トップダウンとは反対に0, 1, 2,....nと要素を昇順に処理していく方式 | ||
step1~3がボトムアップ方式となっている(実装後に用語知りました。。。) | ||
|
||
__・メモ化しながら再帰で解く方法も存在する__ | ||
https://github.com/Yoshiki-Iwasa/Arai60/pull/44/commits/3a55cc495ac31c94e38e1b39f40055ed9d261f18 | ||
|
||
単純に再帰で解くと時間計算量がO(2^n)となるので要素数に比例して実行時間が凄くかかる | ||
このトレードオフとしてメモ化がある(状態を保持しておくためのメモリを要するため) | ||
メモ化しながら存在するというよりは、メモ化しないと時間計算量が爆発的になる | ||
|
||
|
||
__・LRUを使っている__ | ||
なぜ? | ||
https://github.com/goto-untrapped/Arai60/pull/44/commits/b0b76df73f7b0b3c15b5ae4aef0066cfe611eb1b | ||
https://discord.com/channels/1084280443945353267/1226508154833993788/1253725840114454598 | ||
>LRU cacheというのがよく聞かれるのってなんでなんだろう(どういう出題意図なんだろう) | ||
>話の導入がしやすく、助け舟も出しやすく、書けるからですね。 | ||
|
||
なるほど、つまり常識として(使える選択肢として)理解しておくべきか | ||
キャパシティを設定しておいて、超えた場合は自動で削除する | ||
これによって無駄にリソースを使わない | ||
|
||
実装の参考 | ||
https://github.com/goto-untrapped/Arai60/pull/44/commits/b0b76df73f7b0b3c15b5ae4aef0066cfe611eb1b | ||
https://github.com/sakupan102/arai60-practice/pull/31 | ||
LRU.cppに実装 |
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,22 @@ | ||
class Solution { | ||
public: | ||
int numWays(int n, int k) { | ||
if (n == 0) { | ||
return 0; | ||
} | ||
return PaintWays(n, k); | ||
} | ||
|
||
private: | ||
int PaintWays(int num_fence, int num_color) { | ||
if (num_fence == 1) { | ||
return num_color; | ||
} | ||
if (num_fence == 2) { | ||
return num_color * num_color; | ||
} | ||
int diff_paint = (num_color - 1) * PaintWays(num_fence - 1, num_color); | ||
int same_paint = (num_color - 1) * PaintWays(num_fence - 2, num_color); | ||
return diff_paint + same_paint; | ||
} | ||
}; |
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,28 @@ | ||
class Solution { | ||
public: | ||
int numWays(int n, int k) { | ||
if (n == 0) { | ||
return 0; | ||
} | ||
// initialize with impossible value | ||
vector<int> paint_ways_so_far(n + 1, -1); | ||
return PaintWays(paint_ways_so_far, n, k); | ||
} | ||
|
||
private: | ||
int PaintWays(vector<int>& paint_ways_so_far, int num_fence, int num_color) { | ||
if (paint_ways_so_far[num_fence] != -1) { | ||
return paint_ways_so_far[num_fence]; | ||
} | ||
if (num_fence == 1) { | ||
return num_color; | ||
} | ||
if (num_fence == 2) { | ||
return num_color * num_color; | ||
} | ||
int diff_paint = (num_color - 1) * PaintWays(paint_ways_so_far, num_fence - 1, num_color); | ||
int same_paint = (num_color - 1) * PaintWays(paint_ways_so_far, num_fence - 2, num_color); | ||
paint_ways_so_far[num_fence] = diff_paint + same_paint; | ||
return diff_paint + same_paint; | ||
} | ||
}; |
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,27 @@ | ||
class Solution { | ||
public: | ||
int numWays(int num_posts, int num_colors) { | ||
if (num_posts == 0) { | ||
return 0; | ||
} | ||
if (num_posts == 1) { | ||
return num_colors; | ||
} | ||
if (num_posts == 2) { | ||
return num_colors * num_colors; | ||
} | ||
|
||
vector<int> past_two_colors(2); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
past_two_colors[0] = num_colors; | ||
past_two_colors[1] = num_colors * num_colors; | ||
|
||
int colors = 0; | ||
for (int i = 2; i < num_posts; i++) { | ||
colors = (num_colors - 1) * (past_two_colors[0] + past_two_colors[1]); | ||
past_two_colors[0] = past_two_colors[1]; | ||
past_two_colors[1] = colors; | ||
} | ||
|
||
return colors; | ||
} | ||
}; |
Oops, something went wrong.
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.
これ、num_posts が 1000 を超えたらどうなりますかね。
計算時間としては爆発しないようですね。cache サイズが2以上あれば大丈夫ですか?
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.
@oda
レビューありがとうございます。今回の問題(自分の実装の場合)の場合は2で問題なかったです。
皆さんのを写経するだけで、cacheを1000にする理由を考えておりませんでした。
関数CountNumWaysの中で、使うのは今いる箇所から-1したところと-2した箇所の情報だけです。
PutしていてもCacheのサイズ2つ確保しておけば必要な分は消されないので問題なさそうです。
自分の解法だとnum_postsの数はあまり影響しないので、使えてなさそうですね。。。