Skip to content

63. Unique Paths II#32

Open
seal-azarashi wants to merge 5 commits intomainfrom
unique-paths-ii
Open

63. Unique Paths II#32
seal-azarashi wants to merge 5 commits intomainfrom
unique-paths-ii

Conversation

@seal-azarashi
Copy link
Copy Markdown
Owner


public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int rowCount = obstacleGrid.length, columnCount = obstacleGrid[0].length;
int[] uniquePathCache = new int[columnCount];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

キャッシュはそのkeyに対応する値が存在すれば値を算出するための計算をスキップしてその値を返すものとして使われるイメージがあり、この変数にキャッシュと名付けるのは自分には少し違和感がありました。
https://en.wikipedia.org/wiki/Cache_(computing)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@fhiyo
返信が大変遅くなりました。

この変数は命名するのに悩みました。確かに各イテレーションでは計算のスキップは行われないので、cache が名前に含まれている違和感があるのは理解できます。
少し考えてみたのですが、uniquePathCounts とするのはいかがでしょうか?これでしたら key に対応する値がユニークな path の数である以外の意味は含まれないので、上記のような違和感はないかと思います。

continue;
}

if (1 <= x) {
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.

私は、0 < x のほうがマジックナンバー感がなくて好きですね。趣味の範囲でしょう。

int rowCount = obstacleGrid.length, columnCount = obstacleGrid[0].length;
int[][] uniquePathCache = new int[rowCount][columnCount];
for (int i = 0; i < rowCount; i++) {
if (obstacleGrid[i][0] == 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.

1 がマジックナンバーになってるので、名前をつけてあげてほしいです

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@Yoshiki-Iwasa
返信が大変遅くなりました。

仰るとおりですね。step 2 以降定数として宣言するようにしました。


public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int rowCount = obstacleGrid.length, columnCount = obstacleGrid[0].length;
int[] uniquePathCache = new int[columnCount];
Copy link
Copy Markdown

@Yoshiki-Iwasa Yoshiki-Iwasa Oct 7, 2024

Choose a reason for hiding this comment

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

このuniquePathCacheという配列についてコメントで説明がほしいです

uniquePathCache[i] が ある列におけるi行目に到達する方法の数だというのは名前から自明でなく、コードを読んでいかないとわからないので

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@Yoshiki-Iwasa
返信が大変遅くなりました。

そうですね、確かにコメントがあった方が良さそうです。「スタート地点から [i] に到達するまでのステップ数をキャッシュ」と書こうかと思いましたが、充分な説明になってますでしょうか?

return this.uniquePathCount;
}

private void findPathToGoalRecursively(int y, int x) {
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(this.obstacleGrid[y][x] == 1){
            return;
        }

とすれば、L27~29と、L45, L49の後半の条件がいらなくなりますね。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@nittoco
返信が大変遅くなりました。

たしかにそうですね。Step 4 に修正版を加えました: 83d0360

* - O(1): 左端列最初に obstacle が現れる位置
*/
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

個人的にここのコードは読みにくかったです。
このロジックで実装するなら、L116~L131までのどこかで関数化した方が読みやすいかもしれません。

Copy link
Copy Markdown
Owner Author

@seal-azarashi seal-azarashi Oct 28, 2024

Choose a reason for hiding this comment

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

@nittoco
返信が大変遅くなりました。

読みづらさの原因は関数が長いことでしょうか?個人的には30行程度なのであまり違和感を感じませんでしたが、例えば次のようにすれば読みやすくなるでしょうか。

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int rowCount = obstacleGrid.length;
        int columnCount = obstacleGrid[0].length;
        int[] uniquePathCache = createUniquePathCache(columnCount, obstacleGrid);
        int leftColumnFirstObstacleIndex = createLeftColumnFirstObstacleIndex(rowCount, obstacleGrid);

        for (int y = 1; y < rowCount; y++) {
            if (leftColumnFirstObstacleIndex <= y) {
                uniquePathCache[0] = 0;
            } else {
                uniquePathCache[0] = 1;
            }
            for (int x = 1; x < columnCount; x++) {
                if (obstacleGrid[y][x] == 1) {
                    uniquePathCache[x] = 0;
                    continue;
                }
                uniquePathCache[x] += uniquePathCache[x - 1];
            }
        }
        return uniquePathCache[columnCount - 1];
    }

    private int[] createUniquePathCache(int columnCount, int[][] obstacleGrid) {
        int[] uniquePathCache = new int[columnCount];
        for (int i = 0; i < columnCount; i++) {
            if (obstacleGrid[0][i] == 1) {
                break;
            }
            uniquePathCache[i] = 1;
        }
        return uniquePathCache;
    }

    private int createLeftColumnFirstObstacleIndex(int rowCount, int[][] obstacleGrid) {
        int leftColumnFirstObstacleIndex = rowCount;
        for (int i = 0; i < rowCount; i++) {
            if (obstacleGrid[i][0] == 1) {
                leftColumnFirstObstacleIndex = i;
                break;
            }
        }
        return leftColumnFirstObstacleIndex;
    }
}

関数化をしたらしたで、引数に何が来るのかとかを把握しながら読むことになるので、意外とひとつにまとまっていた方が読みやすかったりしないかなとも思ったりするのですが、どうでしょうね。

uniquePathCache[0] = 0;
} else {
uniquePathCache[0] = 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.

細かくて趣味の範囲そうですが、

uniquePathCache[0] = 1;
if (leftColumnFirstObstacleIndex <= y) {
                uniquePathCache[0] = 0;
} 

と自分ならするかも(障害があるより向こう側は0になるというのが特別な感じがするので)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

なるほど、これも良いですね。else 句は適切に使えてるのかいつも悩ましいです。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants