leetCode 刷题 (八)算法入门

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用来存放橘子的位置坐标。

        C++ std::pair的用法 - 白菜菜白 - 博客园

        C++ queue(STL queue)用法详解

21. 合并两个有序链表 

思路:本题比较简单,可以采用非递归的算法实现,这里为了锻炼自己所以才用递归的算法。

对于两个有序链表,我们每次递归实现选择两个头结点中最小的节点接到新链表上即可。

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;
    }
};

206. 反转链表        

思路:采用头插法构造新的链表,得到的结果与原链表顺序相反

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;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值