comments | difficulty | edit_url | tags | ||||
---|---|---|---|---|---|---|---|
true |
Medium |
|
You are given two string arrays, names
and columns
, both of size n
. The ith
table is represented by the name names[i]
and contains columns[i]
number of columns.
You need to implement a class that supports the following operations:
- Insert a row in a specific table with an id assigned using an auto-increment method, where the id of the first inserted row is 1, and the id of each new row inserted into the same table is one greater than the id of the last inserted row, even if the last row was removed.
- Remove a row from a specific table. Removing a row does not affect the id of the next inserted row.
- Select a specific cell from any table and return its value.
- Export all rows from any table in csv format.
Implement the SQL
class:
SQL(String[] names, int[] columns)
<ul> <li>Creates the <code>n</code> tables.</li> </ul> </li> <li><code>bool ins(String name, String[] row)</code> <ul> <li>Inserts <code>row</code> into the table <code>name</code> and returns <code>true</code>.</li> <li>If <code>row.length</code> <strong>does not</strong> match the expected number of columns, or <code>name</code> is <strong>not</strong> a valid table, returns <code>false</code> without any insertion.</li> </ul> </li> <li><code>void rmv(String name, int rowId)</code> <ul> <li>Removes the row <code>rowId</code> from the table <code>name</code>.</li> <li>If <code>name</code> is <strong>not</strong> a valid table or there is no row with id <code>rowId</code>, no removal is performed.</li> </ul> </li> <li><code>String sel(String name, int rowId, int columnId)</code> <ul> <li>Returns the value of the cell at the specified <code>rowId</code> and <code>columnId</code> in the table <code>name</code>.</li> <li>If <code>name</code> is <strong>not</strong> a valid table, or the cell <code>(rowId, columnId)</code> is <strong>invalid</strong>, returns <code>"<null>"</code>.</li> </ul> </li> <li><code>String[] exp(String name)</code> <ul> <li>Returns the rows present in the table <code>name</code>.</li> <li>If name is <strong>not</strong> a valid table, returns an empty array. Each row is represented as a string, with each cell value (<strong>including</strong> the row's id) separated by a <code>","</code>.</li> </ul> </li>
Example 1:
Input:
["SQL","ins","sel","ins","exp","rmv","sel","exp"] [[["one","two","three"],[2,3,1]],["two",["first","second","third"]],["two",1,3],["two",["fourth","fifth","sixth"]],["two"],["two",1],["two",2,2],["two"]]
Output:
[null,true,"third",true,["1,first,second,third","2,fourth,fifth,sixth"],null,"fifth",["2,fourth,fifth,sixth"]]
Explanation:
// Creates three tables. SQL sql = new SQL(["one", "two", "three"], [2, 3, 1]); // Adds a row to the table "two" with id 1. Returns True. sql.ins("two", ["first", "second", "third"]); // Returns the value "third" from the third column // in the row with id 1 of the table "two". sql.sel("two", 1, 3); // Adds another row to the table "two" with id 2. Returns True. sql.ins("two", ["fourth", "fifth", "sixth"]); // Exports the rows of the table "two". // Currently, the table has 2 rows with ids 1 and 2. sql.exp("two"); // Removes the first row of the table "two". Note that the second row // will still have the id 2. sql.rmv("two", 1); // Returns the value "fifth" from the second column // in the row with id 2 of the table "two". sql.sel("two", 2, 2); // Exports the rows of the table "two". // Currently, the table has 1 row with id 2. sql.exp("two");
Example 2:
Input:
["SQL","ins","sel","rmv","sel","ins","ins"] [[["one","two","three"],[2,3,1]],["two",["first","second","third"]],["two",1,3],["two",1],["two",1,2],["two",["fourth","fifth"]],["two",["fourth","fifth","sixth"]]]
Output:
[null,true,"third",null,"<null>",false,true]
Explanation:
// Creates three tables. SQL sQL = new SQL(["one", "two", "three"], [2, 3, 1]); // Adds a row to the table "two" with id 1. Returns True. sQL.ins("two", ["first", "second", "third"]); // Returns the value "third" from the third column // in the row with id 1 of the table "two". sQL.sel("two", 1, 3); // Removes the first row of the table "two". sQL.rmv("two", 1); // Returns "<null>" as the cell with id 1 // has been removed from table "two". sQL.sel("two", 1, 2); // Returns False as number of columns are not correct. sQL.ins("two", ["fourth", "fifth"]); // Adds a row to the table "two" with id 2. Returns True. sQL.ins("two", ["fourth", "fifth", "sixth"]);
Constraints:
n == names.length == columns.length
1 <= n <= 104
1 <= names[i].length, row[i].length, name.length <= 10
names[i]
,row[i]
, andname
consist only of lowercase English letters.1 <= columns[i] <= 10
1 <= row.length <= 10
- All
names[i]
are distinct. - At most
2000
calls will be made toins
andrmv
. - At most
104
calls will be made tosel
. - At most
500
calls will be made toexp
.
Follow-up: Which approach would you choose if the table might become sparse due to many deletions, and why? Consider the impact on memory usage and performance.
Create a hash table tables
to store the mapping of table names to table data rows. Directly simulate the operations in the problem.
The time complexity of each operation is
class SQL:
def __init__(self, names: List[str], columns: List[int]):
self.tables = defaultdict(list)
def insertRow(self, name: str, row: List[str]) -> None:
self.tables[name].append(row)
def deleteRow(self, name: str, rowId: int) -> None:
pass
def selectCell(self, name: str, rowId: int, columnId: int) -> str:
return self.tables[name][rowId - 1][columnId - 1]
# Your SQL object will be instantiated and called as such:
# obj = SQL(names, columns)
# obj.insertRow(name,row)
# obj.deleteRow(name,rowId)
# param_3 = obj.selectCell(name,rowId,columnId)
class SQL {
private Map<String, List<List<String>>> tables;
public SQL(List<String> names, List<Integer> columns) {
tables = new HashMap<>(names.size());
}
public void insertRow(String name, List<String> row) {
tables.computeIfAbsent(name, k -> new ArrayList<>()).add(row);
}
public void deleteRow(String name, int rowId) {
}
public String selectCell(String name, int rowId, int columnId) {
return tables.get(name).get(rowId - 1).get(columnId - 1);
}
}
/**
* Your SQL object will be instantiated and called as such:
* SQL obj = new SQL(names, columns);
* obj.insertRow(name,row);
* obj.deleteRow(name,rowId);
* String param_3 = obj.selectCell(name,rowId,columnId);
*/
class SQL {
public:
unordered_map<string, vector<vector<string>>> tables;
SQL(vector<string>& names, vector<int>& columns) {
}
void insertRow(string name, vector<string> row) {
tables[name].push_back(row);
}
void deleteRow(string name, int rowId) {
}
string selectCell(string name, int rowId, int columnId) {
return tables[name][rowId - 1][columnId - 1];
}
};
/**
* Your SQL object will be instantiated and called as such:
* SQL* obj = new SQL(names, columns);
* obj->insertRow(name,row);
* obj->deleteRow(name,rowId);
* string param_3 = obj->selectCell(name,rowId,columnId);
*/
type SQL struct {
tables map[string][][]string
}
func Constructor(names []string, columns []int) SQL {
return SQL{map[string][][]string{}}
}
func (this *SQL) InsertRow(name string, row []string) {
this.tables[name] = append(this.tables[name], row)
}
func (this *SQL) DeleteRow(name string, rowId int) {
}
func (this *SQL) SelectCell(name string, rowId int, columnId int) string {
return this.tables[name][rowId-1][columnId-1]
}
/**
* Your SQL object will be instantiated and called as such:
* obj := Constructor(names, columns);
* obj.InsertRow(name,row);
* obj.DeleteRow(name,rowId);
* param_3 := obj.SelectCell(name,rowId,columnId);
*/