Press "Enter" to skip to content

Posts tagged as “iterator”

花花酱 LeetCode 2296 Design a Text Editor

方法1:双向链表来存储文本,迭代器指向光标所在的位置。加一个dummy head会使代码简单很多。

时间复杂度:TextEditor O(1) addText O(|text|) deleteText O(k) cursorLeft O(k) cursorRight(k)
空间复杂度:O(n)

由于每个字符需要创建一个节点(17+个字节),虽然没有超时,但实际工程中是不能使用这种方式的。

方法2: 用两个string来代表光标左边的字符串和光标右边的字符串。注:右边字符串是反转的。

左右两边的字符串只会增长(或者覆盖),不会缩短,这是用空间换时间。

删除的时候就是修改了长度而已,并没有缩短字符串,所以是O(1)的。
如果缩短的话需则要O(k)时间,还要加上内存释放/再分配的时间,应该会慢一些但不多。

移动光标的时候,就是把左边字符串的最后k个copy到右边的最后面,或者反过来。同样没有缩短,只会变长。

时间复杂度: TextEditor O(1) addText O(|text|) deleteText O(1) cursorLeft O(k) cursorRight(k)
空间复杂度:O(n),n为构建的最长的字符串

花花酱 LeetCode 2353. Design a Food Rating System

Hashtable + TreeSet / OrderedSet

用了三个Hashtable…

  1. 菜名 -> 菜系
  2. 菜系 -> Treemap
  3. 菜名 -> 所在Treemap中的迭代器

每个菜系用一个TreeSet来保存从高到低的菜色排名,查询的时候只要拿出第一个就好了。

修改的时候,拿出迭代器,删除原来的评分,再把新的评分加入(别忘了更新迭代器)

时间复杂度:构造O(nlogn),修改O(logn),查询O(1)

空间复杂度:O(n)

花花酱 LeetCode 3408. Design Task Manager

  1. pq_ 使用std::map充当优先队列,存储(priority, taskId) -> userId
  2. m_ 使用std::unordered_map,存储taskId -> pq_的迭代器

所有操作都是O(logn)

花花酱 LeetCode 2102. Sequentially Ordinal Rank Tracker

A scenic location is represented by its name and attractiveness score, where name is a unique string among all locations and score is an integer. Locations can be ranked from the best to the worst. The higher the score, the better the location. If the scores of two locations are equal, then the location with the lexicographically smaller name is better.

You are building a system that tracks the ranking of locations with the system initially starting with no locations. It supports:

  • Adding scenic locations, one at a time.
  • Querying the ith best location of all locations already added, where i is the number of times the system has been queried (including the current query).
    • For example, when the system is queried for the 4th time, it returns the 4th best location of all locations already added.

Note that the test data are generated so that at any time, the number of queries does not exceed the number of locations added to the system.

Implement the SORTracker class:

  • SORTracker() Initializes the tracker system.
  • void add(string name, int score) Adds a scenic location with name and score to the system.
  • string get() Queries and returns the ith best location, where i is the number of times this method has been invoked (including this invocation).

Example 1:

Constraints:

  • name consists of lowercase English letters, and is unique among all locations.
  • 1 <= name.length <= 10
  • 1 <= score <= 105
  • At any time, the number of calls to get does not exceed the number of calls to add.
  • At most 4 * 104 calls in total will be made to add and get.

Solution: TreeSet w/ Iterator

Use a treeset to store all the entries and use a iterator that points to the entry to return. When inserting a new entry into the tree, if it’s higher than the current element then let the iterator go backward one step.

Time complexity: add O(logn) / get O(1)

C++

花花酱 LeetCode 1670. Design Front Middle Back Queue

Design a queue that supports push and pop operations in the front, middle, and back.

Implement the FrontMiddleBack class:

  • FrontMiddleBack() Initializes the queue.
  • void pushFront(int val) Adds val to the front of the queue.
  • void pushMiddle(int val) Adds val to the middle of the queue.
  • void pushBack(int val) Adds val to the back of the queue.
  • int popFront() Removes the front element of the queue and returns it. If the queue is empty, return -1.
  • int popMiddle() Removes the middle element of the queue and returns it. If the queue is empty, return -1.
  • int popBack() Removes the back element of the queue and returns it. If the queue is empty, return -1.

Notice that when there are two middle position choices, the operation is performed on the frontmost middle position choice. For example:

  • Pushing 6 into the middle of [1, 2, 3, 4, 5] results in [1, 2, 6, 3, 4, 5].
  • Popping the middle from [1, 2, 3, 4, 5, 6] returns 3 and results in [1, 2, 4, 5, 6].

Example 1:

Input:
["FrontMiddleBackQueue", "pushFront", "pushBack", "pushMiddle", "pushMiddle", "popFront", "popMiddle", "popMiddle", "popBack", "popFront"]
[[], [1], [2], [3], [4], [], [], [], [], []]
Output:
[null, null, null, null, null, 1, 3, 4, 2, -1]
Explanation:
FrontMiddleBackQueue q = new FrontMiddleBackQueue();
q.pushFront(1);   // [1]
q.pushBack(2);    // [1, 2]
q.pushMiddle(3);  // [1, 3, 2]
q.pushMiddle(4);  // [1, 4, 3, 2]
q.popFront();     // return 1 -> [4, 3, 2]
q.popMiddle();    // return 3 -> [4, 2]
q.popMiddle();    // return 4 -> [2]
q.popBack();      // return 2 -> []
q.popFront();     // return -1 -> [] (The queue is empty)

Constraints:

  • 1 <= val <= 109
  • At most 1000 calls will be made to pushFrontpushMiddlepushBackpopFrontpopMiddle, and popBack.

Solution: List + Middle Iterator

Time complexity: O(1) per op
Space complexity: O(n) in total

C++