diff --git a/Arai60/44. Move Zeroes/Makefile b/Arai60/44. Move Zeroes/Makefile new file mode 100644 index 0000000..4ec71d4 --- /dev/null +++ b/Arai60/44. Move Zeroes/Makefile @@ -0,0 +1,9 @@ +NAME = a.out +SRC = main.cpp +CXX = g++ +CXXFLAGS = -Wall -Wextra -Werror -std=c++11 + +all: $(NAME) + +$(NAME): $(SRC) step3.hpp + $(CXX) -o $(NAME) $(SRC) $(CXXFLAGS) diff --git a/Arai60/44. Move Zeroes/main.cpp b/Arai60/44. Move Zeroes/main.cpp index e69de29..dd571b1 100644 --- a/Arai60/44. Move Zeroes/main.cpp +++ b/Arai60/44. Move Zeroes/main.cpp @@ -0,0 +1,26 @@ +#include "step3.hpp" +#include +#include +#include + +void test(std::initializer_list input, + std::initializer_list expected) { + std::vector nums(input); + std::vector expected_nums(expected); + std::cout << "input: "; + for (auto num : nums) { + std::cout << num << " "; + } + Solution().moveZeroes(nums); + // vectorに== operatorが使えるって知らなかった + // https://en.cppreference.com/w/cpp/container/vector/operator_cmp + assert(nums == expected_nums); + std::cout << " ===== OK =====" << std::endl; +} + +int main() { + test({0, 1, 0, 3, 12}, {1, 3, 12, 0, 0}); + test({0}, {0}); + test({0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}); + test({1, 2, 3, 4, 5}, {1, 2, 3, 4, 5}); +} diff --git a/Arai60/44. Move Zeroes/step1.hpp b/Arai60/44. Move Zeroes/step1.hpp new file mode 100644 index 0000000..013847c --- /dev/null +++ b/Arai60/44. Move Zeroes/step1.hpp @@ -0,0 +1,27 @@ +/* + 何がわからなかったか + - N/A + 何を考えて解いていたか + 1. In place -> swapを使いたい + 2. Use two pointers, one for next insert position, the other for cursor + 3. When it == next_it, swap is not necessary but it's okay + 正解してから気づいたこと + - N/A +*/ +#ifndef STEP1_HPP +#define STEP1_HPP +#include +#include +class Solution { +public: + void moveZeroes(std::vector &nums) { + auto next_it = nums.begin(); + for (auto it = nums.begin(); it < nums.end(); ++it) { + if (*it != 0) { + std::iter_swap(next_it, it); + ++next_it; + } + } + } +}; +#endif diff --git a/Arai60/44. Move Zeroes/step2.hpp b/Arai60/44. Move Zeroes/step2.hpp new file mode 100644 index 0000000..9b4d019 --- /dev/null +++ b/Arai60/44. Move Zeroes/step2.hpp @@ -0,0 +1,69 @@ +/* + 講師陣はどのようなコメントを残すだろうか? + - + 他の人のコードを読んで考えたこと + - https://github.com/Yoshiki-Iwasa/Arai60/pull/59/files + 1. retainした後にresizeで0埋めするというのはコードとして見通しが良い + 2. &mut nums[1..]という書き方は、コピーにならないのか + ならないみたい + https://doc.rust-lang.org/book/ch04-03-slices.html + - https://github.com/fhiyo/leetcode/pull/54/files + 1. swapするのではなく, あとでまとめて0埋めする方がloop unrollingが効いて + 嬉しいこともあるというのはなるほど目から鱗だった + 改善する時にかんがえたこと + 1. `std::swap(*next_pos++, num)`とか`*next_pos++ = + num`という書き方もできるけど, error-proneなのでやめた + 2. Iteratorを使わない場合はswapしたいので、numがreferenceとなるよう注意 + 3. 0埋めをあとで行うのは, + filterしたい値が1つだけの場合に有効だが、複数の値をたとえば移動したい場合とかは順番もretainできるしswapがよいかな + */ + +#ifndef STEP2_HPP +#define STEP2_HPP + +#include +#include + +class Solution { +public: + // 1. swapを使う + void moveZeroes1(std::vector &nums) { + auto next_pos = nums.begin(); + for (auto &num : nums) { + if (num != 0) { + std::swap(*next_pos, num); + ++next_pos; + } + } + } + // 1-2. swapを使う (with Iterator) + void moveZeroes12(vector &nums) { + auto next_pos = nums.begin(); + for (auto it = nums.begin(); it != nums.end(); ++it) { + if (*it != 0) { + std::iter_swap(*next_pos, it); + ++next_pos; + } + } + } + // 2. swapを使わないで, 0埋めを後で行う + void moveZeroes2(vector &nums) { + auto next_pos = nums.begin(); + for (auto &num : nums) { + if (num != 0) { + *next_pos = num; + ++next_pos; + } + } + std::fill(next_pos, nums.end(), 0); + } + // 2-2. for/if文をOne-linerっぽく書く (error-proneなので好きではない) + void moveZeroes22(vector &nums) { + auto next_pos = nums.begin(); + for (auto num : nums) + if (num != 0) + *next_pos++ = num; + std::fill(next_pos, nums.end(), 0); + } +}; +#endif diff --git a/Arai60/44. Move Zeroes/step3.hpp b/Arai60/44. Move Zeroes/step3.hpp new file mode 100644 index 0000000..4cfedb6 --- /dev/null +++ b/Arai60/44. Move Zeroes/step3.hpp @@ -0,0 +1,24 @@ +#ifndef STEP3_HPP +#define STEP3_HPP + +#include +#include + +/* + 3問連続で正解するのにかかった時間 2:57 + 時間計算量: O(N) + 空間計算量: O(1) +*/ +class Solution { +public: + void moveZeroes(std::vector &nums) { + auto next = nums.begin(); + for (auto it = nums.begin(); it != nums.end(); ++it) { + if (*it != 0) { + std::iter_swap(it, next); + ++next; + } + } + } +}; +#endif