こんにちは
今回の学びは
・きちんと問題ぶんをよんで入力と出力をおさえましょう。
・どんな状態を記憶してく必要があるのか?で変数を決める
問題はすでにならべられている数字なのですが、重複があるのでそれを省いて、in-placeで書き換えてください
というもんだい
例えば
1, 1, 2だったら1, 2, xをかえしましょう 最後がxなのはなんでもいいからです
ふたつポインターつかって
ひとつは操作パス
もうひとつは書き込みパス としましょう
実装前後でこれは毎回書きましょう。timespace anaylysis (時間とスペースの分析)は 操作パス一発なのでO(n)です
メモリはi, jの変数くらいなのでO(1)です
pseudocode(擬似コード)をかいてみますか。
j = 0 # write pointer
pre = S[0]
for i, x in S:
if x == pre: # duplicate
pass
else:
S[j] = x
j+=1
シンプルですね。たぶん動くでしょう。
で、最初に提出したコードはこちら、ですがサンプルケースで通りません。なにが問題かわかりますでしょうか。
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
j = 1 # write pointer
if nums == None or len(nums) == 0: return 0
pre = nums[0]
dup = 0
dup_pre = None
for i, x in enumerate(nums):
if i == 0:
pass
elif x == pre: # duplicate
if x != dup_pre:
dup += 1
dup_pre = x
else:
nums[j] = x
j+=1
pre = x
return dup
間違いは、重複の数をかえすのではなく、重複を取り除いたあとの配列の長さをかえすべきだったのです。
問題文の入力と出力の理解が間違っていると、
要件定義をちゃんと理解していない、できない、と判断されてもおかしくないので、きちんと問題ぶんをよんで入力と出力をおさえましょう。
実際の実装はこちら
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
j = 1 # write pointer
if nums == None or len(nums) == 0: return 0
pre = nums[0]
dup = 0
dup_pre = None
for i, x in enumerate(nums):
if i == 0:
pass
elif x == pre: # duplicate
if x != dup_pre:
dup += 1
dup_pre = x
else:
nums[j] = x
j+=1
pre = x
return j
なんとか一発パスです

実装後です。timespace anaylysis (時間とスペースの分析)は ◯◯ O(n) and space is O(1)
今回は何回か見たことがある問題ににていたので
パッとふたつのポインターをつかうということが
おもいつきました。
操作パスとは別に書き込み状態を持つ、ということが
発想の原点になるべきですね。
どんな状態を記憶してく必要があるのか?という質問をすることで 必要な変数がみえてきます。あたりまえのことを言っているようですが、これを意識するとぐっとコーディング力が上がります
以上です