From 69a0ba134ede1b0ec19c0ed616603d05448f17ec Mon Sep 17 00:00:00 2001 From: rinost081 <66202148+rinost081@users.noreply.github.com> Date: Sun, 8 Dec 2024 13:49:03 +0900 Subject: [PATCH] step1, step2, step3 --- lc703.md | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 lc703.md diff --git a/lc703.md b/lc703.md new file mode 100644 index 0000000..b824b06 --- /dev/null +++ b/lc703.md @@ -0,0 +1,99 @@ +# step1 +- 愚直に解くなら、初期化時にforループ、その後addされるときにもforループを回す方法. + +- 計算効率を上げるなら、なんとなくキャッシュを作る方法とかがありそうな感じ. + +- forループを愚直に回すとしても、k番目以降は捨てて良いのでそれだけで効率化できそう. + +- リストに対するsortの仕方を忘れていた.sort()をする場合は、破壊的処理をするためにnum = num.sort()としたらNoneが出てくる. + +- この前の勉強会で講師の方がテストケースには空のものを想定するとおっしゃっていて実際のテストケースにも出てたから、それを常に意識するようにしたい. + +- 最終的にstep1で考えたのは、for文を使う方針(計算量を抑える方法が思いつかなかった)で、愚直に毎回for文で回すのではなく大きい順にK番目以降は刈り取ることで少し計算量を抑えた(K番目以降は見る必要がないので).しかしKが大きくなるにつれ刈り取る意味がなくなってくるアルゴリズムになっている. + +```python +class KthLargest: + + def __init__(self, k: int, nums: List[int]): + self.k = k + self.sorted_nums = [] + nums.sort(reverse=True) + + i = 0 + if len(nums) != 0: + while len(nums) > i and self.k != i: + self.sorted_nums.append(nums[i]) + i += 1 + + + def add(self, val: int) -> int: + if len(self.sorted_nums) < self.k: + self.sorted_nums.append(val) + self.sorted_nums.sort(reverse=True) + elif self.sorted_nums[self.k-1] > val: + pass + elif self.sorted_nums[self.k-1] <= val: + del self.sorted_nums[self.k-1] + self.sorted_nums.append(val) + self.sorted_nums.sort(reverse=True) + + return self.sorted_nums[self.k-1] +``` + +# step2 +参考にした方のPR +- https://github.com/BumbuShoji/Leetcode/pull/9 +- https://github.com/konnysh/arai60/pull/8#discussion\_r1866983937 +- https://github.com/katataku/leetcode/pull/8#discussion\_r1862795689 +- https://github.com/haniwachann/leetcode/pull/1 +- https://github.com/tarinaihitori/leetcode/pull/8 + +- step1のadd()関数の中でソート済みのリストに追加した後,再度sortをしているがそうするよりも前から比較して入ってinsertする場所を探すというコメントがあった、その通りな気がする. +- heapに気付けなかった→どうしたら気付けるのか +- pythonにはSortedList()というものがある→nums.sort(), sorted(nums), nums = SortedList()の違いって何 + +## heapを使った解法 +heapは最小(大)値をO(logN)で取り出し、要素をO(logN)で挿入する. またself.addをそのまま使っているため__init__では簡単な処理を書くだけで済む + +```python +class KthLargest: + + def __init__(self, k: int, nums: List[int]): + self.k = k + self.k_largest_nums = [] + + for num in nums: + self.add(num) + + def add(self, val: int) -> int: + heapq.heappush(self.k_largest_nums, val) + + while self.k < len(self.k_largest_nums): + heapq.heappop(self.k_largest_nums) + return self.k_largest_nums[0] +``` + +## nums.sort(), sorted(nums), nums = SortedList()の違いとheapとの比較 +- sort()とsorted()の違いは、前者が元のリストを変えるのに対して後者は新しいリストを作成して元のリストには影響がない点. +- SortedList()は追加したときに自動的にsortされる点 +- sort()とsorted()はTimSortを使用しておりO(nlogn)、SortedList()はO(nlogn)で動く(なんのソートかは探し出せなかった) + +# step3 +```python +class KthLargest: + + def __init__(self, k: int, nums: List[int]): + self.k = k + self.k_largest_nums = [] + + for num in nums: + self.add(num) + + def add(self, val: int) -> int: + heapq.heappush(self.k_largest_nums, val) + + while self.k < len(self.k_largest_nums): + heappop(self.k_largest_nums) + + return self.k_largest_nums[0] +``` \ No newline at end of file