994. 腐烂的橘子994. 腐烂的橘子994. 腐烂的橘子
思路:显然本题可以利用图的广度优先遍历,我们还是把所有腐烂的橘子想象成与一个超级起点相连的点,这样广度优先遍历就可以从一个起点出发。同时,用flag标记本轮是否有新鲜橘子被感染。记录腐烂次数,然后等广度优先遍历处理完后,检查是否还有未腐烂的橘子,如果没有,则返回次数,如果有,则表明有新鲜橘子四周没有腐烂橘子,永远不会腐烂。注意特殊情况:没有橘子、没有腐烂橘子。
class Solution {
public:
static constexpr int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int orangesRotting(vector<vector<int>>& grid) {
int m = grid.size(),n = grid[0].size();
int flag = 0;
int ans = 0;
vector<vector<int>> seen(m, vector<int>(n));//标记当前位置是否被访问
queue<pair<int, int>> q;
//腐烂橘子入队
for(int i=0;i<m;i++){
for(int j=0;j<n;j++)
if(grid[i][j]==2)
{//emplace():用传给 emplace() 的参数调用 T 的构造函数,在 queue 的尾部生成对象。
q.emplace(i,j);
seen[i][j]=1;
}
}
//BFS
while(!q.empty()){
int t = q.size(); //本轮有多少腐烂橘子要去腐烂四周
for(int k =0;k<t;k++){
auto [i, j] = q.front();
q.pop();
//处理上下左右
for (int d = 0; d < 4; ++d) {
int ni = i + dirs[d][0];
int nj = j + dirs[d][1];
if (ni >= 0 && ni < m && nj >= 0 && nj < n && !seen[ni][nj]) {
if(grid[ni][nj]==1){ //为新鲜橘子,则将它腐烂,并标记
grid[ni][nj]=2;
q.emplace(ni, nj);
seen[ni][nj] = 1;
}
}
}
}
//本轮腐烂结束
ans++;
}
//初始没有腐烂橘子
if(ans>0)
ans--;//最后一轮腐烂,没有腐烂任何新鲜橘子
//处理结束,检查是否存在新鲜橘子
for(int i=0;i<m;i++){
for(int j=0;j<n;j++)
if(grid[i][j]==1)
return -1;
}
return ans;
}
};
注:用到了STL中的queue和pair,用法详解,pair用来存放橘子的位置坐标。
思路:本题比较简单,可以采用非递归的算法实现,这里为了锻炼自己所以才用递归的算法。
对于两个有序链表,我们每次递归实现选择两个头结点中最小的节点接到新链表上即可。
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1==nullptr)
return l2;
if(l2==nullptr)
return l1;
ListNode* head;
if(l1->val<=l2->val){
head = l1;
head->next = mergeTwoLists(l1->next,l2);
}
else{
head = l2;
head->next = mergeTwoLists(l1,l2->next);
}
return head;
}
};
思路:采用头插法构造新的链表,得到的结果与原链表顺序相反
class Solution {
public:
ListNode* reverseList(ListNode* head) {
//采用头插法
ListNode *rehead = NULL;
ListNode *tmp = NULL;
ListNode *h = head;
while(h != NULL){
tmp = h;
h = h->next;
tmp->next = rehead;
rehead = tmp;
}
return rehead;
}
};