diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README.md b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README.md index fa9134aadaf49..c048c7f16ad7f 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README.md +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README.md @@ -54,11 +54,13 @@ tags: ### 方法一:滑动窗口 + 哈希表 -我们可以使用滑动窗口的思想,维护一个滑动窗口,使得窗口内的字符串中不同字符的个数不超过 $k$ 个。窗口内不同字符个数的统计可以用哈希表 `cnt` 来维护。 +我们可以使用滑动窗口的思想,用一个哈希表 $\textit{cnt}$ 记录窗口中每个字符的出现次数,用 $\textit{l}$ 记录窗口的左边界。 -我们使用两个指针 $j$ 和 $i$ 分别表示滑动窗口的左右边界。我们先移动右边界 $i$,将字符 $s[i]$ 加入到窗口内,扩大滑动窗口,若此时窗口内不同字符的个数超过 $k$ 个,则移动左边界 $j$,缩小滑动窗口,直到窗口内不同字符的个数不超过 $k$ 个。此时我们可以更新答案的最大值,即 $ans = max(ans, i - j + 1)$。 +遍历字符串,每次将右边界的字符加入哈希表,如果哈希表中不同字符的个数超过了 $k$,则将左边界的字符从哈希表中删除,然后更新左边界 $\textit{l}$。 -时间复杂度 $O(n)$,空间复杂度 $O(\min(n, k))$。其中 $n$ 为字符串的长度。 +最后返回字符串的长度减去左边界的长度即可。 + +时间复杂度 $O(n)$,空间复杂度 $O(k)$。其中 $n$ 为字符串的长度。 @@ -67,18 +69,16 @@ tags: ```python class Solution: def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int: + l = 0 cnt = Counter() - n = len(s) - ans = j = 0 - for i, c in enumerate(s): + for c in s: cnt[c] += 1 - while len(cnt) > k: - cnt[s[j]] -= 1 - if cnt[s[j]] == 0: - cnt.pop(s[j]) - j += 1 - ans = max(ans, i - j + 1) - return ans + if len(cnt) > k: + cnt[s[l]] -= 1 + if cnt[s[l]] == 0: + del cnt[s[l]] + l += 1 + return len(s) - l ``` #### Java @@ -87,22 +87,18 @@ class Solution: class Solution { public int lengthOfLongestSubstringKDistinct(String s, int k) { Map cnt = new HashMap<>(); - int n = s.length(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - char c = s.charAt(i); - cnt.put(c, cnt.getOrDefault(c, 0) + 1); - while (cnt.size() > k) { - char t = s.charAt(j); - cnt.put(t, cnt.getOrDefault(t, 0) - 1); - if (cnt.get(t) == 0) { - cnt.remove(t); + int l = 0; + char[] cs = s.toCharArray(); + for (char c : cs) { + cnt.merge(c, 1, Integer::sum); + if (cnt.size() > k) { + if (cnt.merge(cs[l], -1, Integer::sum) == 0) { + cnt.remove(cs[l]); } - ++j; + ++l; } - ans = Math.max(ans, i - j + 1); } - return ans; + return cs.length - l; } } ``` @@ -114,19 +110,17 @@ class Solution { public: int lengthOfLongestSubstringKDistinct(string s, int k) { unordered_map cnt; - int n = s.size(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - cnt[s[i]]++; - while (cnt.size() > k) { - if (--cnt[s[j]] == 0) { - cnt.erase(s[j]); + int l = 0; + for (char& c : s) { + ++cnt[c]; + if (cnt.size() > k) { + if (--cnt[s[l]] == 0) { + cnt.erase(s[l]); } - ++j; + ++l; } - ans = max(ans, i - j + 1); } - return ans; + return s.size() - l; } }; ``` @@ -134,21 +128,40 @@ public: #### Go ```go -func lengthOfLongestSubstringKDistinct(s string, k int) (ans int) { +func lengthOfLongestSubstringKDistinct(s string, k int) int { cnt := map[byte]int{} - j := 0 - for i := range s { - cnt[s[i]]++ - for len(cnt) > k { - cnt[s[j]]-- - if cnt[s[j]] == 0 { - delete(cnt, s[j]) + l := 0 + for _, c := range s { + cnt[byte(c)]++ + if len(cnt) > k { + cnt[s[l]]-- + if cnt[s[l]] == 0 { + delete(cnt, s[l]) } - j++ + l++ } - ans = max(ans, i-j+1) } - return + return len(s) - l +} +``` + +#### TypeScript + +```ts +function lengthOfLongestSubstringKDistinct(s: string, k: number): number { + const cnt: Map = new Map(); + let l = 0; + for (const c of s) { + cnt.set(c, (cnt.get(c) ?? 0) + 1); + if (cnt.size > k) { + cnt.set(s[l], cnt.get(s[l])! - 1); + if (cnt.get(s[l]) === 0) { + cnt.delete(s[l]); + } + l++; + } + } + return s.length - l; } ``` diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README_EN.md b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README_EN.md index 04562983b147c..8643cc011245e 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README_EN.md +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/README_EN.md @@ -50,7 +50,15 @@ tags: -### Solution 1 +### Solution 1: Sliding Window + Hash Table + +We can use the idea of a sliding window, with a hash table $\textit{cnt}$ to record the occurrence count of each character within the window, and $\textit{l}$ to denote the left boundary of the window. + +Iterate through the string, adding the character at the right boundary to the hash table each time. If the number of distinct characters in the hash table exceeds $k$, remove the character at the left boundary from the hash table, then update the left boundary $\textit{l}$. + +Finally, return the length of the string minus the length of the left boundary. + +The time complexity is $O(n)$, and the space complexity is $O(k)$. Here, $n$ is the length of the string. @@ -59,18 +67,16 @@ tags: ```python class Solution: def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int: + l = 0 cnt = Counter() - n = len(s) - ans = j = 0 - for i, c in enumerate(s): + for c in s: cnt[c] += 1 - while len(cnt) > k: - cnt[s[j]] -= 1 - if cnt[s[j]] == 0: - cnt.pop(s[j]) - j += 1 - ans = max(ans, i - j + 1) - return ans + if len(cnt) > k: + cnt[s[l]] -= 1 + if cnt[s[l]] == 0: + del cnt[s[l]] + l += 1 + return len(s) - l ``` #### Java @@ -79,22 +85,18 @@ class Solution: class Solution { public int lengthOfLongestSubstringKDistinct(String s, int k) { Map cnt = new HashMap<>(); - int n = s.length(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - char c = s.charAt(i); - cnt.put(c, cnt.getOrDefault(c, 0) + 1); - while (cnt.size() > k) { - char t = s.charAt(j); - cnt.put(t, cnt.getOrDefault(t, 0) - 1); - if (cnt.get(t) == 0) { - cnt.remove(t); + int l = 0; + char[] cs = s.toCharArray(); + for (char c : cs) { + cnt.merge(c, 1, Integer::sum); + if (cnt.size() > k) { + if (cnt.merge(cs[l], -1, Integer::sum) == 0) { + cnt.remove(cs[l]); } - ++j; + ++l; } - ans = Math.max(ans, i - j + 1); } - return ans; + return cs.length - l; } } ``` @@ -106,19 +108,17 @@ class Solution { public: int lengthOfLongestSubstringKDistinct(string s, int k) { unordered_map cnt; - int n = s.size(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - cnt[s[i]]++; - while (cnt.size() > k) { - if (--cnt[s[j]] == 0) { - cnt.erase(s[j]); + int l = 0; + for (char& c : s) { + ++cnt[c]; + if (cnt.size() > k) { + if (--cnt[s[l]] == 0) { + cnt.erase(s[l]); } - ++j; + ++l; } - ans = max(ans, i - j + 1); } - return ans; + return s.size() - l; } }; ``` @@ -126,21 +126,40 @@ public: #### Go ```go -func lengthOfLongestSubstringKDistinct(s string, k int) (ans int) { +func lengthOfLongestSubstringKDistinct(s string, k int) int { cnt := map[byte]int{} - j := 0 - for i := range s { - cnt[s[i]]++ - for len(cnt) > k { - cnt[s[j]]-- - if cnt[s[j]] == 0 { - delete(cnt, s[j]) + l := 0 + for _, c := range s { + cnt[byte(c)]++ + if len(cnt) > k { + cnt[s[l]]-- + if cnt[s[l]] == 0 { + delete(cnt, s[l]) } - j++ + l++ } - ans = max(ans, i-j+1) } - return + return len(s) - l +} +``` + +#### TypeScript + +```ts +function lengthOfLongestSubstringKDistinct(s: string, k: number): number { + const cnt: Map = new Map(); + let l = 0; + for (const c of s) { + cnt.set(c, (cnt.get(c) ?? 0) + 1); + if (cnt.size > k) { + cnt.set(s[l], cnt.get(s[l])! - 1); + if (cnt.get(s[l]) === 0) { + cnt.delete(s[l]); + } + l++; + } + } + return s.length - l; } ``` diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.cpp b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.cpp index 4c7a64f5dc076..55461d59a01c0 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.cpp +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.cpp @@ -2,18 +2,16 @@ class Solution { public: int lengthOfLongestSubstringKDistinct(string s, int k) { unordered_map cnt; - int n = s.size(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - cnt[s[i]]++; - while (cnt.size() > k) { - if (--cnt[s[j]] == 0) { - cnt.erase(s[j]); + int l = 0; + for (char& c : s) { + ++cnt[c]; + if (cnt.size() > k) { + if (--cnt[s[l]] == 0) { + cnt.erase(s[l]); } - ++j; + ++l; } - ans = max(ans, i - j + 1); } - return ans; + return s.size() - l; } }; \ No newline at end of file diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.go b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.go index a70eb7c6cf17d..9d88aa75a300d 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.go +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.go @@ -1,16 +1,15 @@ -func lengthOfLongestSubstringKDistinct(s string, k int) (ans int) { +func lengthOfLongestSubstringKDistinct(s string, k int) int { cnt := map[byte]int{} - j := 0 - for i := range s { - cnt[s[i]]++ - for len(cnt) > k { - cnt[s[j]]-- - if cnt[s[j]] == 0 { - delete(cnt, s[j]) + l := 0 + for _, c := range s { + cnt[byte(c)]++ + if len(cnt) > k { + cnt[s[l]]-- + if cnt[s[l]] == 0 { + delete(cnt, s[l]) } - j++ + l++ } - ans = max(ans, i-j+1) } - return + return len(s) - l } \ No newline at end of file diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.java b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.java index 556133f79cd1d..d1f50fc755fdc 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.java +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.java @@ -1,21 +1,17 @@ class Solution { public int lengthOfLongestSubstringKDistinct(String s, int k) { Map cnt = new HashMap<>(); - int n = s.length(); - int ans = 0, j = 0; - for (int i = 0; i < n; ++i) { - char c = s.charAt(i); - cnt.put(c, cnt.getOrDefault(c, 0) + 1); - while (cnt.size() > k) { - char t = s.charAt(j); - cnt.put(t, cnt.getOrDefault(t, 0) - 1); - if (cnt.get(t) == 0) { - cnt.remove(t); + int l = 0; + char[] cs = s.toCharArray(); + for (char c : cs) { + cnt.merge(c, 1, Integer::sum); + if (cnt.size() > k) { + if (cnt.merge(cs[l], -1, Integer::sum) == 0) { + cnt.remove(cs[l]); } - ++j; + ++l; } - ans = Math.max(ans, i - j + 1); } - return ans; + return cs.length - l; } } \ No newline at end of file diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.py b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.py index e5f136e2c70ed..3644fac6eda6a 100644 --- a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.py +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.py @@ -1,14 +1,12 @@ class Solution: def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int: + l = 0 cnt = Counter() - n = len(s) - ans = j = 0 - for i, c in enumerate(s): + for c in s: cnt[c] += 1 - while len(cnt) > k: - cnt[s[j]] -= 1 - if cnt[s[j]] == 0: - cnt.pop(s[j]) - j += 1 - ans = max(ans, i - j + 1) - return ans + if len(cnt) > k: + cnt[s[l]] -= 1 + if cnt[s[l]] == 0: + del cnt[s[l]] + l += 1 + return len(s) - l diff --git a/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.ts b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.ts new file mode 100644 index 0000000000000..2865634a94d6a --- /dev/null +++ b/solution/0300-0399/0340.Longest Substring with At Most K Distinct Characters/Solution.ts @@ -0,0 +1,15 @@ +function lengthOfLongestSubstringKDistinct(s: string, k: number): number { + const cnt: Map = new Map(); + let l = 0; + for (const c of s) { + cnt.set(c, (cnt.get(c) ?? 0) + 1); + if (cnt.size > k) { + cnt.set(s[l], cnt.get(s[l])! - 1); + if (cnt.get(s[l]) === 0) { + cnt.delete(s[l]); + } + l++; + } + } + return s.length - l; +} diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/README.md b/solution/0300-0399/0341.Flatten Nested List Iterator/README.md index 616325863bc88..6a7fe407546a1 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/README.md +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/README.md @@ -108,24 +108,23 @@ return res class NestedIterator: def __init__(self, nestedList: [NestedInteger]): - def dfs(nestedList): - for e in nestedList: - if e.isInteger(): - self.vals.append(e.getInteger()) + def dfs(ls): + for x in ls: + if x.isInteger(): + self.nums.append(x.getInteger()) else: - dfs(e.getList()) + dfs(x.getList()) - self.vals = [] + self.nums = [] + self.i = -1 dfs(nestedList) - self.cur = 0 def next(self) -> int: - res = self.vals[self.cur] - self.cur += 1 - return res + self.i += 1 + return self.nums[self.i] def hasNext(self) -> bool: - return self.cur < len(self.vals) + return self.i + 1 < len(self.nums) # Your NestedIterator object will be instantiated and called as such: @@ -149,38 +148,34 @@ class NestedIterator: * public Integer getInteger(); * * // @return the nested list that this NestedInteger holds, if it holds a nested list - * // Return null if this NestedInteger holds a single integer + * // Return empty list if this NestedInteger holds a single integer * public List getList(); * } */ public class NestedIterator implements Iterator { - - private List vals; - - private Iterator cur; + private List nums = new ArrayList<>(); + private int i = -1; public NestedIterator(List nestedList) { - vals = new ArrayList<>(); dfs(nestedList); - cur = vals.iterator(); } @Override public Integer next() { - return cur.next(); + return nums.get(++i); } @Override public boolean hasNext() { - return cur.hasNext(); + return i + 1 < nums.size(); } - private void dfs(List nestedList) { - for (NestedInteger e : nestedList) { - if (e.isInteger()) { - vals.add(e.getInteger()); + private void dfs(List ls) { + for (var x : ls) { + if (x.isInteger()) { + nums.add(x.getInteger()); } else { - dfs(e.getList()); + dfs(x.getList()); } } } @@ -217,30 +212,29 @@ public class NestedIterator implements Iterator { class NestedIterator { public: NestedIterator(vector& nestedList) { - dfs(nestedList); + auto dfs = [&](auto&& dfs, vector& ls) -> void { + for (auto& x : ls) { + if (x.isInteger()) { + nums.push_back(x.getInteger()); + } else { + dfs(dfs, x.getList()); + } + } + }; + dfs(dfs, nestedList); } int next() { - return vals[cur++]; + return nums[++i]; } bool hasNext() { - return cur < vals.size(); + return i + 1 < nums.size(); } private: - vector vals; - int cur = 0; - - void dfs(vector& nestedList) { - for (auto& e : nestedList) { - if (e.isInteger()) { - vals.push_back(e.getInteger()); - } else { - dfs(e.getList()); - } - } - } + vector nums; + int i = -1; }; /** @@ -280,34 +274,34 @@ private: */ type NestedIterator struct { - iterator []int - index, length int + nums []int + i int } func Constructor(nestedList []*NestedInteger) *NestedIterator { - result := make([]int, 0) - var traversal func(nodes []*NestedInteger) - traversal = func(nodes []*NestedInteger) { - for _, child := range nodes { - if child.IsInteger() { - result = append(result, child.GetInteger()) + var dfs func([]*NestedInteger) + nums := []int{} + i := -1 + dfs = func(ls []*NestedInteger) { + for _, x := range ls { + if x.IsInteger() { + nums = append(nums, x.GetInteger()) } else { - traversal(child.GetList()) + dfs(x.GetList()) } } } - traversal(nestedList) - return &NestedIterator{iterator: result, index: 0, length: len(result)} + dfs(nestedList) + return &NestedIterator{nums, i} } func (this *NestedIterator) Next() int { - res := this.iterator[this.index] - this.index++ - return res + this.i++ + return this.nums[this.i] } func (this *NestedIterator) HasNext() bool { - return this.index < this.length + return this.i+1 < len(this.nums) } ``` @@ -354,31 +348,27 @@ func (this *NestedIterator) HasNext() bool { */ class NestedIterator { - private vals: number[]; - private index: number; - + private nums: number[] = []; + private i = -1; constructor(nestedList: NestedInteger[]) { - this.index = 0; - this.vals = []; - this.dfs(nestedList); - } - - dfs(nestedList: NestedInteger[]) { - for (const v of nestedList) { - if (v.isInteger()) { - this.vals.push(v.getInteger()); - } else { - this.dfs(v.getList()); + const dfs = (ls: NestedInteger[]) => { + for (const x of ls) { + if (x.isInteger()) { + this.nums.push(x.getInteger()); + } else { + dfs(x.getList()); + } } - } + }; + dfs(nestedList); } hasNext(): boolean { - return this.index < this.vals.length; + return this.i + 1 < this.nums.length; } next(): number { - return this.vals[this.index++]; + return this.nums[++this.i]; } } @@ -399,8 +389,8 @@ class NestedIterator { // List(Vec) // } struct NestedIterator { - index: usize, - vals: Vec, + nums: Vec, + i: usize, } /** @@ -408,102 +398,30 @@ struct NestedIterator { * If you need a mutable reference, change it to `&mut self` instead. */ impl NestedIterator { - fn dfs(nestedList: &Vec, vals: &mut Vec) { - for ele in nestedList.iter() { - match ele { - NestedInteger::Int(val) => vals.push(*val), - NestedInteger::List(list) => Self::dfs(list, vals), - } - } - } - - fn new(nestedList: Vec) -> Self { - let mut vals = vec![]; - Self::dfs(&nestedList, &mut vals); - Self { vals, index: 0 } + fn new(nested_list: Vec) -> Self { + let mut nums = Vec::new(); + Self::dfs(&nested_list, &mut nums); + NestedIterator { nums, i: 0 } } fn next(&mut self) -> i32 { - let res = self.vals[self.index]; - self.index += 1; - res + let result = self.nums[self.i]; + self.i += 1; + result } fn has_next(&self) -> bool { - self.index < self.vals.len() + self.i < self.nums.len() } -} -``` - - - - - - - -### 方法二:直接展开 - -调用 hasNext 时,如果 nestedList 的第一个元素是列表类型,则不断展开这个元素,直到第一个元素是整数类型。 调用 Next 方法时,由于 `hasNext()` 方法已确保 nestedList 第一个元素为整数类型,直接返回即可。 - - - -#### Go - -```go -/** - * // This is the interface that allows for creating nested lists. - * // You should not implement it, or speculate about its implementation - * type NestedInteger struct { - * } - * - * // Return true if this NestedInteger holds a single integer, rather than a nested list. - * func (this NestedInteger) IsInteger() bool {} - * - * // Return the single integer that this NestedInteger holds, if it holds a single integer - * // The result is undefined if this NestedInteger holds a nested list - * // So before calling this method, you should have a check - * func (this NestedInteger) GetInteger() int {} - * - * // Set this NestedInteger to hold a single integer. - * func (n *NestedInteger) SetInteger(value int) {} - * - * // Set this NestedInteger to hold a nested list and adds a nested integer to it. - * func (this *NestedInteger) Add(elem NestedInteger) {} - * - * // Return the nested list that this NestedInteger holds, if it holds a nested list - * // The list length is zero if this NestedInteger holds a single integer - * // You can access NestedInteger's List element directly if you want to modify it - * func (this NestedInteger) GetList() []*NestedInteger {} - */ - -type NestedIterator struct { - nested *list.List -} - -func Constructor(nestedList []*NestedInteger) *NestedIterator { - nested := list.New() - for _, v := range nestedList { - nested.PushBack(v) - } - return &NestedIterator{nested: nested} -} -func (this *NestedIterator) Next() int { - res := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - return res.GetInteger() -} - -func (this *NestedIterator) HasNext() bool { - for this.nested.Len() > 0 && !this.nested.Front().Value.(*NestedInteger).IsInteger() { - front := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - nodes := front.GetList() - for i := len(nodes) - 1; i >= 0; i-- { - this.nested.PushFront(nodes[i]) - } - } - return this.nested.Len() > 0 + fn dfs(nested_list: &Vec, nums: &mut Vec) { + for ni in nested_list { + match ni { + NestedInteger::Int(x) => nums.push(*x), + NestedInteger::List(list) => Self::dfs(list, nums), + } + } + } } ``` diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/README_EN.md b/solution/0300-0399/0341.Flatten Nested List Iterator/README_EN.md index 7346931361926..52cf400e9057b 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/README_EN.md +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/README_EN.md @@ -106,24 +106,23 @@ return res class NestedIterator: def __init__(self, nestedList: [NestedInteger]): - def dfs(nestedList): - for e in nestedList: - if e.isInteger(): - self.vals.append(e.getInteger()) + def dfs(ls): + for x in ls: + if x.isInteger(): + self.nums.append(x.getInteger()) else: - dfs(e.getList()) + dfs(x.getList()) - self.vals = [] + self.nums = [] + self.i = -1 dfs(nestedList) - self.cur = 0 def next(self) -> int: - res = self.vals[self.cur] - self.cur += 1 - return res + self.i += 1 + return self.nums[self.i] def hasNext(self) -> bool: - return self.cur < len(self.vals) + return self.i + 1 < len(self.nums) # Your NestedIterator object will be instantiated and called as such: @@ -147,38 +146,34 @@ class NestedIterator: * public Integer getInteger(); * * // @return the nested list that this NestedInteger holds, if it holds a nested list - * // Return null if this NestedInteger holds a single integer + * // Return empty list if this NestedInteger holds a single integer * public List getList(); * } */ public class NestedIterator implements Iterator { - - private List vals; - - private Iterator cur; + private List nums = new ArrayList<>(); + private int i = -1; public NestedIterator(List nestedList) { - vals = new ArrayList<>(); dfs(nestedList); - cur = vals.iterator(); } @Override public Integer next() { - return cur.next(); + return nums.get(++i); } @Override public boolean hasNext() { - return cur.hasNext(); + return i + 1 < nums.size(); } - private void dfs(List nestedList) { - for (NestedInteger e : nestedList) { - if (e.isInteger()) { - vals.add(e.getInteger()); + private void dfs(List ls) { + for (var x : ls) { + if (x.isInteger()) { + nums.add(x.getInteger()); } else { - dfs(e.getList()); + dfs(x.getList()); } } } @@ -215,30 +210,29 @@ public class NestedIterator implements Iterator { class NestedIterator { public: NestedIterator(vector& nestedList) { - dfs(nestedList); + auto dfs = [&](auto&& dfs, vector& ls) -> void { + for (auto& x : ls) { + if (x.isInteger()) { + nums.push_back(x.getInteger()); + } else { + dfs(dfs, x.getList()); + } + } + }; + dfs(dfs, nestedList); } int next() { - return vals[cur++]; + return nums[++i]; } bool hasNext() { - return cur < vals.size(); + return i + 1 < nums.size(); } private: - vector vals; - int cur = 0; - - void dfs(vector& nestedList) { - for (auto& e : nestedList) { - if (e.isInteger()) { - vals.push_back(e.getInteger()); - } else { - dfs(e.getList()); - } - } - } + vector nums; + int i = -1; }; /** @@ -278,34 +272,34 @@ private: */ type NestedIterator struct { - iterator []int - index, length int + nums []int + i int } func Constructor(nestedList []*NestedInteger) *NestedIterator { - result := make([]int, 0) - var traversal func(nodes []*NestedInteger) - traversal = func(nodes []*NestedInteger) { - for _, child := range nodes { - if child.IsInteger() { - result = append(result, child.GetInteger()) + var dfs func([]*NestedInteger) + nums := []int{} + i := -1 + dfs = func(ls []*NestedInteger) { + for _, x := range ls { + if x.IsInteger() { + nums = append(nums, x.GetInteger()) } else { - traversal(child.GetList()) + dfs(x.GetList()) } } } - traversal(nestedList) - return &NestedIterator{iterator: result, index: 0, length: len(result)} + dfs(nestedList) + return &NestedIterator{nums, i} } func (this *NestedIterator) Next() int { - res := this.iterator[this.index] - this.index++ - return res + this.i++ + return this.nums[this.i] } func (this *NestedIterator) HasNext() bool { - return this.index < this.length + return this.i+1 < len(this.nums) } ``` @@ -352,31 +346,27 @@ func (this *NestedIterator) HasNext() bool { */ class NestedIterator { - private vals: number[]; - private index: number; - + private nums: number[] = []; + private i = -1; constructor(nestedList: NestedInteger[]) { - this.index = 0; - this.vals = []; - this.dfs(nestedList); - } - - dfs(nestedList: NestedInteger[]) { - for (const v of nestedList) { - if (v.isInteger()) { - this.vals.push(v.getInteger()); - } else { - this.dfs(v.getList()); + const dfs = (ls: NestedInteger[]) => { + for (const x of ls) { + if (x.isInteger()) { + this.nums.push(x.getInteger()); + } else { + dfs(x.getList()); + } } - } + }; + dfs(nestedList); } hasNext(): boolean { - return this.index < this.vals.length; + return this.i + 1 < this.nums.length; } next(): number { - return this.vals[this.index++]; + return this.nums[++this.i]; } } @@ -397,8 +387,8 @@ class NestedIterator { // List(Vec) // } struct NestedIterator { - index: usize, - vals: Vec, + nums: Vec, + i: usize, } /** @@ -406,100 +396,30 @@ struct NestedIterator { * If you need a mutable reference, change it to `&mut self` instead. */ impl NestedIterator { - fn dfs(nestedList: &Vec, vals: &mut Vec) { - for ele in nestedList.iter() { - match ele { - NestedInteger::Int(val) => vals.push(*val), - NestedInteger::List(list) => Self::dfs(list, vals), - } - } - } - - fn new(nestedList: Vec) -> Self { - let mut vals = vec![]; - Self::dfs(&nestedList, &mut vals); - Self { vals, index: 0 } + fn new(nested_list: Vec) -> Self { + let mut nums = Vec::new(); + Self::dfs(&nested_list, &mut nums); + NestedIterator { nums, i: 0 } } fn next(&mut self) -> i32 { - let res = self.vals[self.index]; - self.index += 1; - res + let result = self.nums[self.i]; + self.i += 1; + result } fn has_next(&self) -> bool { - self.index < self.vals.len() + self.i < self.nums.len() } -} -``` - - - - - - -### Solution 2 - - - -#### Go - -```go -/** - * // This is the interface that allows for creating nested lists. - * // You should not implement it, or speculate about its implementation - * type NestedInteger struct { - * } - * - * // Return true if this NestedInteger holds a single integer, rather than a nested list. - * func (this NestedInteger) IsInteger() bool {} - * - * // Return the single integer that this NestedInteger holds, if it holds a single integer - * // The result is undefined if this NestedInteger holds a nested list - * // So before calling this method, you should have a check - * func (this NestedInteger) GetInteger() int {} - * - * // Set this NestedInteger to hold a single integer. - * func (n *NestedInteger) SetInteger(value int) {} - * - * // Set this NestedInteger to hold a nested list and adds a nested integer to it. - * func (this *NestedInteger) Add(elem NestedInteger) {} - * - * // Return the nested list that this NestedInteger holds, if it holds a nested list - * // The list length is zero if this NestedInteger holds a single integer - * // You can access NestedInteger's List element directly if you want to modify it - * func (this NestedInteger) GetList() []*NestedInteger {} - */ - -type NestedIterator struct { - nested *list.List -} - -func Constructor(nestedList []*NestedInteger) *NestedIterator { - nested := list.New() - for _, v := range nestedList { - nested.PushBack(v) - } - return &NestedIterator{nested: nested} -} - -func (this *NestedIterator) Next() int { - res := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - return res.GetInteger() -} - -func (this *NestedIterator) HasNext() bool { - for this.nested.Len() > 0 && !this.nested.Front().Value.(*NestedInteger).IsInteger() { - front := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - nodes := front.GetList() - for i := len(nodes) - 1; i >= 0; i-- { - this.nested.PushFront(nodes[i]) - } - } - return this.nested.Len() > 0 + fn dfs(nested_list: &Vec, nums: &mut Vec) { + for ni in nested_list { + match ni { + NestedInteger::Int(x) => nums.push(*x), + NestedInteger::List(list) => Self::dfs(list, nums), + } + } + } } ``` diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.cpp b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.cpp index 69d86e084e52e..dde245ec010a3 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.cpp +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.cpp @@ -19,30 +19,29 @@ class NestedIterator { public: NestedIterator(vector& nestedList) { - dfs(nestedList); + auto dfs = [&](auto&& dfs, vector& ls) -> void { + for (auto& x : ls) { + if (x.isInteger()) { + nums.push_back(x.getInteger()); + } else { + dfs(dfs, x.getList()); + } + } + }; + dfs(dfs, nestedList); } int next() { - return vals[cur++]; + return nums[++i]; } bool hasNext() { - return cur < vals.size(); + return i + 1 < nums.size(); } private: - vector vals; - int cur = 0; - - void dfs(vector& nestedList) { - for (auto& e : nestedList) { - if (e.isInteger()) { - vals.push_back(e.getInteger()); - } else { - dfs(e.getList()); - } - } - } + vector nums; + int i = -1; }; /** diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.go b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.go index 231ed7a9e0f43..197f4c40cf885 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.go +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.go @@ -25,32 +25,32 @@ */ type NestedIterator struct { - iterator []int - index, length int + nums []int + i int } func Constructor(nestedList []*NestedInteger) *NestedIterator { - result := make([]int, 0) - var traversal func(nodes []*NestedInteger) - traversal = func(nodes []*NestedInteger) { - for _, child := range nodes { - if child.IsInteger() { - result = append(result, child.GetInteger()) + var dfs func([]*NestedInteger) + nums := []int{} + i := -1 + dfs = func(ls []*NestedInteger) { + for _, x := range ls { + if x.IsInteger() { + nums = append(nums, x.GetInteger()) } else { - traversal(child.GetList()) + dfs(x.GetList()) } } } - traversal(nestedList) - return &NestedIterator{iterator: result, index: 0, length: len(result)} + dfs(nestedList) + return &NestedIterator{nums, i} } func (this *NestedIterator) Next() int { - res := this.iterator[this.index] - this.index++ - return res + this.i++ + return this.nums[this.i] } func (this *NestedIterator) HasNext() bool { - return this.index < this.length + return this.i+1 < len(this.nums) } \ No newline at end of file diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.java b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.java index 04b6ca8ae5181..128e938680a14 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.java +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.java @@ -11,38 +11,34 @@ * public Integer getInteger(); * * // @return the nested list that this NestedInteger holds, if it holds a nested list - * // Return null if this NestedInteger holds a single integer + * // Return empty list if this NestedInteger holds a single integer * public List getList(); * } */ public class NestedIterator implements Iterator { - - private List vals; - - private Iterator cur; + private List nums = new ArrayList<>(); + private int i = -1; public NestedIterator(List nestedList) { - vals = new ArrayList<>(); dfs(nestedList); - cur = vals.iterator(); } @Override public Integer next() { - return cur.next(); + return nums.get(++i); } @Override public boolean hasNext() { - return cur.hasNext(); + return i + 1 < nums.size(); } - private void dfs(List nestedList) { - for (NestedInteger e : nestedList) { - if (e.isInteger()) { - vals.add(e.getInteger()); + private void dfs(List ls) { + for (var x : ls) { + if (x.isInteger()) { + nums.add(x.getInteger()); } else { - dfs(e.getList()); + dfs(x.getList()); } } } diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.py b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.py index 54cc88ffca22a..5f2cae5423011 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.py +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.py @@ -23,24 +23,23 @@ class NestedIterator: def __init__(self, nestedList: [NestedInteger]): - def dfs(nestedList): - for e in nestedList: - if e.isInteger(): - self.vals.append(e.getInteger()) + def dfs(ls): + for x in ls: + if x.isInteger(): + self.nums.append(x.getInteger()) else: - dfs(e.getList()) + dfs(x.getList()) - self.vals = [] + self.nums = [] + self.i = -1 dfs(nestedList) - self.cur = 0 def next(self) -> int: - res = self.vals[self.cur] - self.cur += 1 - return res + self.i += 1 + return self.nums[self.i] def hasNext(self) -> bool: - return self.cur < len(self.vals) + return self.i + 1 < len(self.nums) # Your NestedIterator object will be instantiated and called as such: diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.rs b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.rs index abf739460a20e..e0dc3fa5f7608 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.rs +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.rs @@ -4,8 +4,8 @@ // List(Vec) // } struct NestedIterator { - index: usize, - vals: Vec, + nums: Vec, + i: usize, } /** @@ -13,28 +13,28 @@ struct NestedIterator { * If you need a mutable reference, change it to `&mut self` instead. */ impl NestedIterator { - fn dfs(nestedList: &Vec, vals: &mut Vec) { - for ele in nestedList.iter() { - match ele { - NestedInteger::Int(val) => vals.push(*val), - NestedInteger::List(list) => Self::dfs(list, vals), - } - } - } - - fn new(nestedList: Vec) -> Self { - let mut vals = vec![]; - Self::dfs(&nestedList, &mut vals); - Self { vals, index: 0 } + fn new(nested_list: Vec) -> Self { + let mut nums = Vec::new(); + Self::dfs(&nested_list, &mut nums); + NestedIterator { nums, i: 0 } } fn next(&mut self) -> i32 { - let res = self.vals[self.index]; - self.index += 1; - res + let result = self.nums[self.i]; + self.i += 1; + result } fn has_next(&self) -> bool { - self.index < self.vals.len() + self.i < self.nums.len() + } + + fn dfs(nested_list: &Vec, nums: &mut Vec) { + for ni in nested_list { + match ni { + NestedInteger::Int(x) => nums.push(*x), + NestedInteger::List(list) => Self::dfs(list, nums), + } + } } } diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.ts b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.ts index f838f81053122..99d5f2fd029d4 100644 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.ts +++ b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution.ts @@ -38,31 +38,27 @@ */ class NestedIterator { - private vals: number[]; - private index: number; - + private nums: number[] = []; + private i = -1; constructor(nestedList: NestedInteger[]) { - this.index = 0; - this.vals = []; - this.dfs(nestedList); - } - - dfs(nestedList: NestedInteger[]) { - for (const v of nestedList) { - if (v.isInteger()) { - this.vals.push(v.getInteger()); - } else { - this.dfs(v.getList()); + const dfs = (ls: NestedInteger[]) => { + for (const x of ls) { + if (x.isInteger()) { + this.nums.push(x.getInteger()); + } else { + dfs(x.getList()); + } } - } + }; + dfs(nestedList); } hasNext(): boolean { - return this.index < this.vals.length; + return this.i + 1 < this.nums.length; } next(): number { - return this.vals[this.index++]; + return this.nums[++this.i]; } } diff --git a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution2.go b/solution/0300-0399/0341.Flatten Nested List Iterator/Solution2.go deleted file mode 100644 index 0a7520dd9a266..0000000000000 --- a/solution/0300-0399/0341.Flatten Nested List Iterator/Solution2.go +++ /dev/null @@ -1,55 +0,0 @@ -/** - * // This is the interface that allows for creating nested lists. - * // You should not implement it, or speculate about its implementation - * type NestedInteger struct { - * } - * - * // Return true if this NestedInteger holds a single integer, rather than a nested list. - * func (this NestedInteger) IsInteger() bool {} - * - * // Return the single integer that this NestedInteger holds, if it holds a single integer - * // The result is undefined if this NestedInteger holds a nested list - * // So before calling this method, you should have a check - * func (this NestedInteger) GetInteger() int {} - * - * // Set this NestedInteger to hold a single integer. - * func (n *NestedInteger) SetInteger(value int) {} - * - * // Set this NestedInteger to hold a nested list and adds a nested integer to it. - * func (this *NestedInteger) Add(elem NestedInteger) {} - * - * // Return the nested list that this NestedInteger holds, if it holds a nested list - * // The list length is zero if this NestedInteger holds a single integer - * // You can access NestedInteger's List element directly if you want to modify it - * func (this NestedInteger) GetList() []*NestedInteger {} - */ - -type NestedIterator struct { - nested *list.List -} - -func Constructor(nestedList []*NestedInteger) *NestedIterator { - nested := list.New() - for _, v := range nestedList { - nested.PushBack(v) - } - return &NestedIterator{nested: nested} -} - -func (this *NestedIterator) Next() int { - res := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - return res.GetInteger() -} - -func (this *NestedIterator) HasNext() bool { - for this.nested.Len() > 0 && !this.nested.Front().Value.(*NestedInteger).IsInteger() { - front := this.nested.Front().Value.(*NestedInteger) - this.nested.Remove(this.nested.Front()) - nodes := front.GetList() - for i := len(nodes) - 1; i >= 0; i-- { - this.nested.PushFront(nodes[i]) - } - } - return this.nested.Len() > 0 -} \ No newline at end of file diff --git a/solution/0300-0399/0342.Power of Four/README.md b/solution/0300-0399/0342.Power of Four/README.md index 1fb23b3b6308c..1e71bac29bc3f 100644 --- a/solution/0300-0399/0342.Power of Four/README.md +++ b/solution/0300-0399/0342.Power of Four/README.md @@ -63,7 +63,13 @@ tags: -### 方法一 +### 方法一:位运算 + +如果一个数是 4 的幂次方,那么这个数必须是大于 $0$ 的。不妨假设这个数是 $4^x$,即 $2^{2x}$,那么这个数的二进制表示中有且仅有一个 $1$,且这个 $1$ 出现在偶数位上。 + +因此,我们首先判断这个数是否大于 $0$,然后判断这个数是否是 $2^{2x}$,即 $n$ 与 $n-1$ 的按位与结果是否为 $0$,最后判断这个数的 $1$ 是否出现在偶数位上,即 $n$ 与 $\textit{0xAAAAAAAA}$ 的按位与结果是否为 $0$。如果这三个条件都满足,那么这个数就是 4 的幂次方。 + +时间复杂度 $O(1)$,空间复杂度 $O(1)$。 diff --git a/solution/0300-0399/0342.Power of Four/README_EN.md b/solution/0300-0399/0342.Power of Four/README_EN.md index 785bb147db19d..d74f994dc6c3d 100644 --- a/solution/0300-0399/0342.Power of Four/README_EN.md +++ b/solution/0300-0399/0342.Power of Four/README_EN.md @@ -49,7 +49,13 @@ tags: -### Solution 1 +### Solution 1: Bit Manipulation + +If a number is a power of 4, then it must be greater than $0$. Suppose this number is $4^x$, which is $2^{2x}$. Therefore, its binary representation has only one $1$, and this $1$ appears at an even position. + +First, we check if the number is greater than $0$. Then, we verify if the number is $2^{2x}$ by checking if the bitwise AND of $n$ and $n-1$ is $0$. Finally, we check if the $1$ appears at an even position by verifying if the bitwise AND of $n$ and $\textit{0xAAAAAAAA}$ is $0$. If all three conditions are met, then the number is a power of 4. + +The time complexity is $O(1)$, and the space complexity is $O(1)$.