LeetCode_Nov_1st_Week

Posted 清水寺扫地僧

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode_Nov_1st_Week相关的知识,希望对你有一定的参考价值。

November 1st:575. 分糖果
November 2nd:237. 删除链表中的节点
November 3rd: 407. 接雨水 II


November 1st : 575. 分糖果

偶数长度数组表示糖果的个数,要求弟弟妹妹均分后,妹妹所得糖果的最大种类数是多少。

贪心思想,对于妹妹而言,每种糖果都先取一个,已经取过的种类的糖果都给弟弟:

  • 如果糖果种类数大于等于数组长度的一半,则所获最大种类数即为数组长度的一半;
  • 如果糖果种类数小于数组长度的一半,则所获最大种类数即为糖果的种类数;
//version 1
class Solution {
public:
    int distributeCandies(vector<int>& candyType) {
        unordered_set<int> types;
        for(auto candy : candyType) 
            if(types.find(candy) == types.end()) 
                types.insert(candy);
        return min(types.size(), candyType.size()/2);
    }
};
//version 2
class Solution {
public:
	int distributeCandier(vector<int>& candyType) {
		return min(unordered_set<int>(candyType.begin(), candyType.end()).size(),
		           candyType.size()/2);
	}
};

November 2nd : 237. 删除链表中的节点

给定要删除的节点的指针作为函数参数,则我们无法得到要删除节点的pre节点。

作为替代,则将要删除节点的值赋给要删除的节点node->val = node->next->val,再将要删除节点的next指向要删除节点的next的next节点node->next = node->next->next即可。

评论:脑筋急转弯,没啥意思。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        node->val = node->next->val;
        node->next = node->next->next;
    }
};

November 3rd : 407. 接雨水 II

使用图的广度优先遍历来解决,想一下木桶效应,对于一个被周围四个格子包围的格子而言,其储水的多少应当是:

around_height_min =  min(height_up, height_down, height_left, height_right);
height_cur > around_height_min ? height_cur - around_height_min : 0;

所以需要用到周边格子的最小高度,那么将广度优先遍历所使用的队列替换为优先队列,也即最小堆即可。

对地图进行遍历时,每次取出已遍历过的格子中最矮的那个,将其四周的格子的储水量进行计算,累加,并更新遍历集。重复这个操作,直至遍历完整个地图,即可得到题解。

class Solution {
public:
    int trapRainWater(vector<vector<int>>& heightMap) {
        int m = heightMap.size(), n = heightMap[0].size();
        if(m <= 2 || n <= 2) return 0; //若是地图长宽不均大于2,则无法接到雨水
        //创建最小堆,也即是每次从堆中取出的格子,都是堆中最矮的
        priority_queue<pair<int,int>, vector<pair<int, int>>, greater<pair<int, int>>> heap;
        //记录是否已经处理过
        vector<vector<bool>> visited(m, vector<bool>(n, false));
        //由于边界的格子不可能储水,所以将处于边界的格子加入到堆中去,并标记处理过
        for(int i = 0; i < m; ++i) {
            for(int j = 0; j < n; ++j) {
                if(i == 0 || i == m-1 || j == 0 || j == n-1) {
                    heap.push({heightMap[i][j], i*n+j});
                    visited[i][j] = true;
                }
            }
        }
        int ret = 0;
        //四个方向数组,具体方向见下
        vector<int> direct = {0, 1, 0, -1, 0}; //up right down left
        //只要堆不空,说明格子没有完全处理完,则继续取出进行处理
        while(!heap.empty()) {
            int curHeight = heap.top().first; //所取出格子的高度
            int curX = heap.top().second / n, curY = heap.top().second % n; //所取出格子的坐标
            heap.pop();
            for(int k = 0; k < 4; ++k) { //沿着四个方向取出在地图中且未处理的格子
                int solX = curX + direct[k], solY = curY + direct[k+1];
                if(solX > 0 && solX < m && solY > 0 && solY < n && !visited[solX][solY]) {
                    if(heightMap[solX][solY] < curHeight) { //如果旁边的格子高度小于所取格子高度,则可储水
                        ret += curHeight - heightMap[solX][solY]; //也即是进行广度优先图遍历
                    }
                    visited[solX][solY] = true; //再进行标记
                    heap.push({max(heightMap[solX][solY], curHeight), solX*n+solY}); //将旁边格子加入到最小堆
                    //max(heightMap[solX][solY], curHeight)对于[solX][solY]的旁边格子,储水高度是依照旁边格子的
                    //若是所取格子高度小于[solX][solY]格子,则加入堆时,应当是heightMap[solX][solY]
                }
            }
        }
        return ret;
    }
};

以上是关于LeetCode_Nov_1st_Week的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode_Dec_1st_Week

LeetCode_Nov_5th_Week

LeetCode_Nov_4th_Week

LeetCode_Nov_3rd_Week

LeetCode_Nov_2nd_Week

这些 C++ 代码片段有啥作用?