diff --git a/Python3/283. Move Zeroes.md b/Python3/283. Move Zeroes.md new file mode 100644 index 0000000..acb9679 --- /dev/null +++ b/Python3/283. Move Zeroes.md @@ -0,0 +1,101 @@ +## Step 1. Initial Solution + +- 前から見て行って0が出てきたら後ろに持っていく + - popしてappendするか代入するか + - 全部ずらす処理を書くよりはpopの方が分かりやすい +- for文で見ていくと後ろが0だけになったときに無限ループするので0の出現回数を保持 + +```python +class Solution: + def moveZeroes(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + zero_count = 0 + for i in range(len(nums)): + while nums[i] == 0 and i < len(nums) - zero_count: + nums.pop(i) + nums.append(0) + zero_count += 1 +``` + +### Complexity Analysis + +- 時間計算量:O(N^2) +- 空間計算量:O(1) + +## Step 2. Alternatives + +- Follow upに最小のオペレーション数でやる方法は?とあるので考えてみる + - 0の出現箇所を保持して線形に処理(O(N)) + + ```python + class Solution: + def moveZeroes(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + non_zero_indices = [] + nums_len = len(nums) + + for i in range(len(nums)): + if nums[i] != 0: + non_zero_indices.append(i) + + nums_non_zero = len(non_zero_indices) + for i in range(nums_len): + if i < nums_non_zero: + nums[i] = nums[non_zero_indices[i]] + continue + nums[i] = 0 + ``` + + - 0の出現回数だけ保持してあとで0を足す方法 + + ```python + class Solution: + def moveZeroes(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + index = 0 + zero_count = 0 + nums_len = len(nums) + while index + zero_count < nums_len: + if nums[index + zero_count] == 0: + zero_count += 1 + continue + nums[index] = nums[index + zero_count] + index += 1 + for i in range(index, nums_len): + nums[i] = 0 + ``` + +- https://github.com/tokuhirat/LeetCode/pull/54/files#diff-8e38546decaf9631b00de9e6cb4e27b61427defe98e3406a20c969beaa9f7d18R33 + - この書き方はとてもシンプルで分かりやすい + - x, y = y, xという書き方が出来ることはあまり分かっていなかった + - 右側の評価をして (y, x)のタプル作成→代入、という流れで処理されるらしい +- https://github.com/shining-ai/leetcode/pull/54/files#diff-326ca2ce90ef5e7bf7e21c2676a184474a21c4d3d213d13c81e3fc5675c23267R4 + - これも読みやすい + - 0の時の処理はスキップの方が分岐ごとの処理が見やすくなる +- https://github.com/shintaro1993/arai60/pull/58/files#diff-f10c3b5bb7c73707f74cd5cd8e947fd5882cdde6933460eeba70f9d1b19d840cR31-R40 + - このあたりも忘れずに考えたい + - O(N^2)だと>10^8ステップなので1秒以上かかる + +## Step 3. Final Solution + +- 一番シンプルに感じたもので実装 + +```python +class Solution: + def moveZeroes(self, nums: List[int]) -> None: + """ + Do not return anything, modify nums in-place instead. + """ + non_zero_count = 0 + for i in range(len(nums)): + if nums[i] == 0: + continue + nums[non_zero_count], nums[i] = nums[i], nums[non_zero_count] + non_zero_count += 1 +```