Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions CapacityToShipPackagesWithinDDays/step1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
```java
// Using binary search to find the minimum cap that we can ship the packages
// Min(left) will be the max value in the array, Max(right) will be sum of the values(when we need to ship everything in a day)
// During the search, if we can ship it meaning the smallest cap in left ~ mid
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これでよいと思いますが、二分探索はいくつか書き方があるので、レビューワーの方が、リンクを探し出してまとめてくれることを期待します。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// if we can't, meaning we need to search between mid + 1 ~ right
// Time complexity: O(NlogM) -> N: number of weights, M: sum of values - max value
// Space complexity: O(1)
// Time spend: 08:34
class Solution {
public int shipWithinDays(int[] weights, int days) {
int l = -1;
int r = 0;
for (int w : weights) {
if (w > l) {
l = w;
}
r += w;
}

while (l < r) {
int mid = (l + r) / 2;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この問題の場合は問題とならないと思うのですが、 l + r が int の範囲を超えてオーバーフローするのを防ぐため、 int mid = l + (r - l) / 2; と書いておいたほうが良いと思います。
https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%8E%A2%E7%B4%A2#%E5%AE%9F%E8%A3%85%E4%B8%8A%E3%81%AE%E9%96%93%E9%81%95%E3%81%84

よくある間違いの一つは、上記のC言語のコードで imin + (imax - imin) / 2 を (imax + imin) / 2 としてしまう事である。(imax + imin) / 2 では、imax + imin が int の値の上限 (INT_MAX) を超えて不正な値になってしまう可能性がある。(imax + imin が INT_MAX を超える可能性が全くないと保証できる場合は問題ない。)

if (canShip(weights, mid, days)) {
r = mid;
} else {
l = mid + 1;
}
}

return l;
}

public boolean canShip(int[] weights, int cap, int days) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

capacity でいい気がします。

int day = 1;
int temp = 0;
for (int w : weights) {
if (temp + w <= cap) {
temp += w;
continue;
}
day++;
if (day > days) {
return false;
}
temp = w;
}

return true;
}
}
```
43 changes: 43 additions & 0 deletions CapacityToShipPackagesWithinDDays/step2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
```java
// Time spend: 03:21
class Solution {
public int shipWithinDays(int[] weights, int days) {
int l = -1;
int r = 0;
for (int weight : weights) {
if (weight > l) {
l = weight;
}
r += weight;
}

while (l < r) {
int mid = (l + r) / 2;
if (canShip(weights, mid, days)) {
r = mid;
} else {
l = mid + 1;
}
Comment on lines +16 to +20
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

個人的に、こちらの方が Step3 よりも二分探索だ~と分かりやすかったです。

}

return l;
}

public boolean canShip(int[] weights, int cap, int days) {
int daysNeed = 1;
int currWeight = 0;
for (int weight : weights) {
if (currWeight + weight > cap) {
daysNeed++;
if (daysNeed > days) {
return false;
}
currWeight = 0;
}
currWeight += weight;
}

return true;
}
}
```
127 changes: 127 additions & 0 deletions CapacityToShipPackagesWithinDDays/step3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
```java
// Time spend: 03:11
class Solution {
public int shipWithinDays(int[] weights, int days) {
int l = -1;
int r = 0;
for (int weight : weights) {
if (weight > l) {
l = weight;
}
r += weight;
}

while (l < r) {
int mid = (l + r) / 2;
if (canShip(weights, mid, days)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@goto-untrapped さんも指摘されている点ですが、 l と r の対称性を示すため、 continue せず if else としたほうが良いと思います。

r = mid;
continue;
}
l = mid + 1;
}

return l;
}

public boolean canShip(int[] weights, int cap, int days) {
int daysNeed = 1;
int currWeight = 0;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

変数名に単語の省略形を使用すると、読むにあたり認知負荷が高くなるように思います。チーム内で合意形成が得られているもの以外については、フルスペルで書くことをお勧めいたします。

for (int weight : weights) {
if (currWeight + weight > cap) {
currWeight = 0;
daysNeed++;
if (daysNeed > days) {
return false;
}
}
currWeight += weight;
}

return true;
}
}
```

```java
// Time spend: 02:47
class Solution {
public int shipWithinDays(int[] weights, int days) {
int l = -1;
int r = 0;
for (int w : weights) {
l = Math.max(w, l);
r += w;
}

while (l < r) {
int mid = (l + r) / 2;
if (canShip(weights, days, mid)) {
r = mid;
continue;
}
l = mid + 1;
}

return l;
}

public boolean canShip(int[] weights, int days, int cap) {
int daysNeed = 1;
int currWeight = 0;
for (int w : weights) {
if (currWeight + w > cap) {
currWeight = 0;
daysNeed++;
if (daysNeed > days) {
return false;
}
}
currWeight += w;
}

return true;
}
}
```

```java
// Time spend: 02:21
class Solution {
public int shipWithinDays(int[] weights, int days) {
int l = -1;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

個人的には l = 0 での初期化の方が自然な気がしました。

int r = 0;
for (int w : weights) {
l = Math.max(l, w);
r += w;
}

while (l < r) {
int mid = (l + r) / 2;
if (canShip(weights, days, mid)) {
r = mid;
continue;
}
l = mid + 1;
}

return l;
}

public boolean canShip(int[] weights, int days, int cap) {
int daysNeed = 1;
int currWeight = 0;
for (int w : weights) {
if (currWeight + w > cap) {
currWeight = 0;
daysNeed++;
if (daysNeed > days) {
return false;
}
Comment on lines +117 to +119
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

関数末尾でreturn daysNeed <= daysとするほうが条件分岐が少なくて読みやすいと思いました

早期returnで余計なloopを回さないという意図はあると思うですが、僅かな差だと思うので可読性があがるほうが良いかなと

}
currWeight += w;
}

return true;
}
}
```