[LeetCode] Design a Todo List

2590. Design a Todo List

Design a Todo List Where users can add tasks, mark them as complete, or get a list of pending tasks. Users can also add tags to tasks and can filter the tasks by certain tags.

Implement the TodoList class:

  • TodoList() Initializes the object.
  • int addTask(int userId, String taskDescription, int dueDate, List<String> tags) Adds a task for the user with the ID userId with a due date equal to dueDate and a list of tags attached to the task. The return value is the ID of the task. This ID starts at 1 and is sequentially increasing. That is, the first task’s id should be 1, the second task’s id should be 2, and so on.
  • List<String> getAllTasks(int userId) Returns a list of all the tasks not marked as complete for the user with ID userId, ordered by the due date. You should return an empty list if the user has no uncompleted tasks.
  • List<String> getTasksForTag(int userId, String tag) Returns a list of all the tasks that are not marked as complete for the user with the ID userId and have tag as one of their tags, ordered by their due date. Return an empty list if no such task exists.
  • void completeTask(int userId, int taskId) Marks the task with the ID taskId as completed only if the task exists and the user with the ID userId has this task, and it is uncompleted.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

struct Task {
string desc;
vector<string> tags;
int dueDate;
int id;
};
class TodoList {
int idGen = 0;
unordered_map<int, unordered_map<string,unordered_set<int>>> tagRef;
unordered_map<int, unordered_map<int, Task>> taskRef;
int incr(int userId) {
return ++idGen;
}
vector<string> sortByDueDate(vector<Task>& A) {
sort(begin(A), end(A), [](auto a, auto b) {return a.dueDate < b.dueDate;});
vector<string> res;
for(auto t : A) res.push_back(t.desc);
return res;
}
public:
TodoList() {}

int addTask(int userId, string taskDescription, int dueDate, vector<string> tags) {
int id = incr(userId);
Task task{taskDescription, tags, dueDate, id};
taskRef[userId][id] = task;
for(auto t : tags) tagRef[userId][t].insert(id);
return id;
}

vector<string> getAllTasks(int userId) {
vector<Task> A;
for(auto [id, t] : taskRef[userId]) A.push_back(t);
return sortByDueDate(A);
}

vector<string> getTasksForTag(int userId, string tag) {
vector<Task> A;
for(auto id : tagRef[userId][tag]) A.push_back(taskRef[userId][id]);
return sortByDueDate(A);
}

void completeTask(int userId, int taskId) {
if(!taskRef.count(userId)) return;
if(!taskRef[userId].count(taskId)) return;
Task t = taskRef[userId][taskId];
taskRef[userId].erase(taskId);
if(taskRef[userId].empty()) taskRef.erase(userId);
for(auto& tag : t.tags) {
tagRef[userId][tag].erase(t.id);
if(tagRef[userId][tag].empty()) tagRef[userId].erase(tag);
if(tagRef[userId].empty()) tagRef.erase(userId);
}
}
};

/**
* Your TodoList object will be instantiated and called as such:
* TodoList* obj = new TodoList();
* int param_1 = obj->addTask(userId,taskDescription,dueDate,tags);
* vector<string> param_2 = obj->getAllTasks(userId);
* vector<string> param_3 = obj->getTasksForTag(userId,tag);
* obj->completeTask(userId,taskId);
*/

Author: Song Hayoung
Link: https://songhayoung.github.io/2023/04/11/PS/LeetCode/design-a-todo-list/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.