Skip to content

Conversation

@Ryotaro25
Copy link
Owner

問題へのリンク
https://leetcode.com/problems/subsets/description/

問題文(プレミアムの場合)

備考

次に解く問題の予告
Combination Sum

フォルダ構成
LeetCodeの問題ごとにフォルダを作成します。
フォルダ内は、step1.cpp、step2.cpp、step3.cpp、cascading.cppとmemo.mdとなります。

memo.md内に各ステップで感じたことを追記します。


for (int num : nums) {
vector<vector<int>> partial_subset;
for (auto prev_subset : all_subsets) {
Copy link

Choose a reason for hiding this comment

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

auto にすると、コピーが発生します。auto& でいいでしょう。(か、下でコピーしているので、auto にしてもいいんですが、そうするとコピーが故意なのかどうかがよく分からなくなりますね。)

Copy link
Owner Author

Choose a reason for hiding this comment

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

@oda
すっかりこの視点が抜けておりました🙇毎日コードを書かないとですね。

Comment on lines +16 to +18
for (auto subset : partial_subset) {
all_subsets.push_back(subset);
}
Copy link

Choose a reason for hiding this comment

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

ここも2度コピーされています。

Copy link
Owner Author

Choose a reason for hiding this comment

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

@oda
vectorのコピーが走りそうな部分は、emplace_backに置き換えました。
bd2f03c

Copy link

Choose a reason for hiding this comment

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

vector の中に入るところでコピーされるのはいたしかたがないので push_back でも構わないと私は思います。
emplace_back だとコンストラクターが動きますね。

indexを使って、サイズを管理している
自分もstep1の時に行なっていたが、サイズの管理は再帰関数の呼び出し回数に吸収させたい
yieldを何か調べた。一時停止させてまた再開をすると処理を追うのが大変そう。。。
あとC++にはなさそう
Copy link

Choose a reason for hiding this comment

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

https://en.cppreference.com/w/cpp/language/coroutines
C++ には coroutine が C++20 からあります。使われているのをみたことがあまりないですが。

Copy link

Choose a reason for hiding this comment

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

別の問題ですが coroutine 使った人はいます。
https://discord.com/channels/1084280443945353267/1247673286503039020/1263415894030290945

}

private:
void GenerateSubset(vector<vector<int>>& all_subsets, vector<int>& partial_subset,

Choose a reason for hiding this comment

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

function 名をcamel かsnakeに統一した方が読みやすいのかと思いました

Copy link

Choose a reason for hiding this comment

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

C++ の場合は UpperCamel にすることが多いと思います。ただ、 LeetCode で指定されている関数名については、指定されているものをそのまま使うしかないと思います。実際には所属するチームの平均的な書き方に合わせて書くことをお勧めいたします。

Copy link
Owner Author

Choose a reason for hiding this comment

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

@austyhooong @nodchip
レビューありがとうございます。
C++はこの会以外で使ったことがなく、会社でも使っていないため下記のグーグルガイドを参考にしております。
https://google.github.io/styleguide/cppguide.html#Function_Names

public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> all_subsets;
vector<int> partial_subset = {};

Choose a reason for hiding this comment

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

default initialization で充分かと思います

Copy link
Owner Author

Choose a reason for hiding this comment

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

@austyhooong
vectorのようにいつも初期化されるものとそうでないものがあるため覚えられないため明示的に初期化しておりました。
effective c++の4項そのような記述があり、そうしておりました🙇

cloned.push_back(num);
partial_subset.push_back(cloned);
}
// この周回で作った集合を次の周回に渡すための処理
Copy link

Choose a reason for hiding this comment

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

all_subsets.insert(all_subsets.end(), partial_subet.begin(), partial_subset.end());
と書くこともできます。

}

private:
void GenerateSubset(vector<vector<int>>& all_subsets, vector<int>& partial_subset,
Copy link

Choose a reason for hiding this comment

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

関数の引数の並びについて、入力を先、出力を後とする流儀があります。

https://google.github.io/styleguide/cppguide.html#Inputs_and_Outputs

When ordering function parameters, put all input-only parameters before any output parameters.

Copy link
Owner Author

Choose a reason for hiding this comment

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

@nodchip ありがとうございます。

continue;
}
partial_subset.push_back(nums[i]);
GenerateSubset(all_subsets, partial_subset, nums,subset_size, i + 1);
Copy link

Choose a reason for hiding this comment

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

, のあとにスペースを空けることをお勧めいたします。

フォーマッターでフォーマットしてもよいと思います。

Copy link
Owner Author

Choose a reason for hiding this comment

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

@nodchip
意図的にフォーマッターをエディタから消していたのですが最後のチェックで入れていてもいいかもですね🙇

vector<int> partial_subset;
all_subsets.push_back({});

for (int i = 1; i <= nums.size(); i++) {
Copy link

Choose a reason for hiding this comment

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

問題文に any order とあるため、部分集合のサイズ順に all_subsets に格納する必要はないと思います。 step2 のほうがシンプルでよいと思います。

Copy link
Owner Author

Choose a reason for hiding this comment

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

@nodchip
解説を読んで分かりました。チェックありがとうございます。

vector<int>& partial_subset, const vector<int>& nums) {
all_subsets.push_back(partial_subset);

for (int i = start; i < nums.size(); i++) {
Copy link

Choose a reason for hiding this comment

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

ここで for 文を回さず、 start の場所にある値を partial_subset に入れるか入れないかで分岐する方法もあります。

void GenerateSubset(const vector<int>& nums, int index, vector<int>& partial_subset, vector<vector<int>>& all_subsets) {
    if (index == nums.size()) {
        all_subsets.push_back(partial_subset);
        return;
    }

    GenerateSubset(nums, index + 1, partial_subset, all_subsets);
    partial_subset.push_back(nums[index]);
    GenerateSubset(nums, index + 1, partial_subset, all_subsets);
    partial_subset.pop_back();
}

Copy link
Owner Author

Choose a reason for hiding this comment

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

@nodchip
ありがとうございます。
選ばない場合と選ぶ場合で再帰を呼び出すのですね。
for で回す方が自分には理解しやすかったです。

}

private:
void GenerateSubset(vector<vector<int>>& all_subsets, vector<int>& partial_subset,
Copy link

Choose a reason for hiding this comment

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

C++ の場合は UpperCamel にすることが多いと思います。ただ、 LeetCode で指定されている関数名については、指定されているものをそのまま使うしかないと思います。実際には所属するチームの平均的な書き方に合わせて書くことをお勧めいたします。

all_subsets.push_back({});

for (int num : nums) {
vector<vector<int>> partial_subset;
Copy link

Choose a reason for hiding this comment

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

partial_subsetは、具体的にどういうものか少し名称としてわかりにくく感じます。
この場合、numを含むsubsetなので、subset_including_numなどでしょうか?

Copy link
Owner Author

Choose a reason for hiding this comment

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

@nittoco
レビューありがとうございます。
バックトラッキング全般ですが変数名に困っており、レビューいただけるのは有り難いです。
下記で使わせていただきました。
bd2f03c

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.

6 participants