289.生命游戏
题目
根据 百度百科 , 生命游戏 ,简称为 生命 ,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
给定一个包含 m × n
个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态: 1
即为 活细胞 (live),或 0
即为 死细胞 (dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
- 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
- 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
- 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
- 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。给你m x n
网格面板board
的当前状态,返回下一个状态。
数据范围
m == board.length
n == board[i].length
1 <= m, n <= 25
board[i][j]
为0
或1
分析
遍历整个矩阵,将活着的细胞死亡后的状态设置为1
,将原本死亡的细胞复活后的状态设置为2
,就可以与原本活着的和原本死亡的细胞进行区分,这里要注意,活着细胞死亡在计算它周围八个细胞状态时需要将-1
的格子也统计进去。
代码
class Solution {
public:
int dx[8] = {0, 1, 0, -1, 1, -1, 1, -1};
int dy[8] = {-1, 0, 1, 0, 1, -1, -1, 1};
void gameOfLife(vector<vector<int>>& board) {
int n = board.size(), m = board[0].size();
for(int i = 0; i < n; i ++ ) {
for(int j = 0; j < m; j ++ ) {
int cnt = 0;
for(int k = 0; k < 8; k ++ ) {
int nx = i + dx[k];
int ny = j + dy[k];
if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if(board[nx][ny] == 1 || board[nx][ny] == -1) cnt ++ ;
}
if((cnt < 2 || cnt > 3) && board[i][j] == 1) board[i][j] = -1;
else if(cnt == 3 && board[i][j] != 1) board[i][j] = 2;
}
}
for(int i = 0; i < n; i ++ ) {
for(int j = 0; j < m; j ++ ) {
// cout << board[i][j] << " ";
if(board[i][j] == -1) board[i][j] = 0;
else if(board[i][j] == 2) board[i][j] = 1;
}
// cout << endl;
}
}
};
380. O(1) 时间插入、删除和获取随机元素
题目
实现RandomizedSet
类:
RandomizedSet()
初始化RandomizedSet
对象bool insert(int val)
当元素val
不存在时,向集合中插入该项,并返回true
;否则,返回false
。bool remove(int val)
当元素val
存在时,从集合中移除该项,并返回true
;否则,返回 false 。int getRandom()
随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 相同的概率 被返回。
你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为O(1)
。
数据范围
-231 <= val <= 231 - 1
- 最多调用
insert
、remove
和getRandom
函数2 * 105
次 - 在调用
getRandom
方法时,数据结构中 至少存在一个 元素。
分析
选择使用一个数组和hash
表来实现,hash
表中存的是数组元素和下表的对应关系,
- 对于
insert
,首先hash
查找是否有对应元素- 若有,则返回
false
- 否则,在数组尾部插入元素,并修改
hash
映射的值
- 若有,则返回
- 对于
delete
,首先hash查找是否有对应元素- 若无,则返回
false
- 否则,找出对应位置
pos
,将数组尾部的值放入pos
,并删除尾部,同时更新hash
映射的值,注意,删除val的hash值需要在修改尾部元素的hash值之后
- 若无,则返回
代码
class RandomizedSet {
public:
unordered_map<int, int> hx;
vector<int> arr;
RandomizedSet() {
srand(time(0));
}
bool insert(int val) {
if(hx.find(val) != hx.end()) return false;
arr.push_back(val);
hx[val] = arr.size() - 1;
return true;
}
bool remove(int val) {
if(hx.find(val) == hx.end()) return false;
int pos = hx[val];
int ed = arr.back();
arr[pos] = ed;
arr.pop_back();
hx[ed] = pos;
hx.erase(val);
return true;
}
int getRandom() {
int pos = rand() % arr.size();
return arr[pos];
}
};
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet* obj = new RandomizedSet();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/
3275.第K近障碍物查询
题目
有一个无限大的二维平面。
给你一个正整数 k
,同时给你一个二维数组 queries
,包含一系列查询:
queries[i] = [x, y]
:在平面上坐标(x, y)
处建一个障碍物,数据保证之前的查询 不会 在这个坐标处建立任何障碍物。
每次查询后,你需要找到离原点第k
近 障碍物到原点的 距离 。
请你返回一个整数数组 results
,其中results[i]
表示建立第 i
个障碍物以后,离原地第 k
近障碍物距离原点的距离。如果少于 k
个障碍物,results[i] == -1
。
注意,一开始 没有 任何障碍物。
坐标在 (x, y)
处的点距离原点的距离定义为 |x| + |y|
。
数据范围
1 <= queries.length <= 2 * 10
- 所有
queries[i]
互不相同。 -109 <= queries[i][0], queries[i][1] <= 109
1 <= k <= 105
分析
如果每次添加元素在sort的话会超时(按道理2e5*log(2e5)不会t才对…不清楚),所以就只能采用建小根堆的方式做,维护一个大小为k
的小顶堆,若当前插入的障碍物离原点距离比堆顶小,则入堆,堆顶元素即是答案
代码
class Solution {
public:
const static int N = 1e5 + 5;
int dis[N];
priority_queue<int, vector<int>, less<int>> heap;
vector<int> resultsArray(vector<vector<int>>& queries, int k) {
int n = queries.size();
vector<int> res;
int idx = 0;
for(int i = 0; i < n; i ++ ) {
int x = queries[i][0];
int y = queries[i][1];
int tdis = abs(x) + abs(y);
heap.push(tdis);
if(heap.size() > k) heap.pop();
if(heap.size() < k) res.push_back(-1);
else if(heap.size() >= k) res.push_back(heap.top());
}
return res;
}
};