LeetCode中级算法之设计问题
二叉树的序列化与反序列化
Question:
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
示例:
你可以将以下二叉树:
1
/ \
2 3
/ \
4 5
序列化为 "[1,2,3,null,null,4,5]"
Solution:
这题就是之前的遍历二叉树,采用先序遍历得到序列化,再按先序反序列化即可,值得注意的是,要记录null的子树,不然无法反序列化。这里贴大神的帖子,以后有时间再写一遍:
https://blog.csdn.net/sinat_15723179/article/details/81431796
Insert Delete GetRandom O(1)
Question:
设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构。
insert(val):当元素 val 不存在时,向集合中插入该项。
remove(val):元素 val 存在时,从集合中移除该项。
getRandom:随机返回现有集合中的一项。每个元素应该有相同的概率被返回。
示例 :
// 初始化一个空的集合。
RandomizedSet randomSet = new RandomizedSet();
// 向集合中插入 1 。返回 true 表示 1 被成功地插入。
randomSet.insert(1);
// 返回 false ,表示集合中不存在 2 。
randomSet.remove(2);
// 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。
randomSet.insert(2);
// getRandom 应随机返回 1 或 2 。
randomSet.getRandom();
// 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。
randomSet.remove(1);
// 2 已在集合中,所以返回 false 。
randomSet.insert(2);
// 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。
randomSet.getRandom();
Solution:
能支持O(1)时间删除,查询的只有hashmap,但是题目还要求随机返回,rand()的复杂度也是1,但是没法用在hashmap里,所以还是要用数组来表示这个数据结构,同时用hashmap存储每个数字在数组中的位置,在删除的时候,先把这个数字和数组末尾的数交换(利用hashmap),再删除数组的末尾元素:
class RandomizedSet {
public:
/** Initialize your data structure here. */
/** Initialize your data structure here. */
RandomizedSet() {
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val) {
if(record[val]) return false;
nums.push_back(val);
record[val] = nums.size();
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val) {
if(!record[val]) return false;
int tail = nums[nums.size() - 1];
record[tail] = record[val];
nums[record[val] - 1] = tail;
record.erase(val);
nums.pop_back();
return true;
}
/** Get a random element from the set. */
int getRandom() {
int i = rand() % nums.size();
return nums[i];
}
private:
vector<int> nums;
map<int,int> record;
};