LeetCode 575. 分糖果 / 237. 删除链表中的节点 / 407. 接雨水 II

Posted Zephyr丶J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 575. 分糖果 / 237. 删除链表中的节点 / 407. 接雨水 II相关的知识,希望对你有一定的参考价值。

575. 分糖果

2021.11.01 每日一题

题目描述

Alice 有 n 枚糖,其中第 i 枚糖的类型为 candyType[i] 。Alice 注意到她的体重正在增长,所以前去拜访了一位医生。

医生建议 Alice 要少摄入糖分,只吃掉她所有糖的 n / 2 即可(n 是一个偶数)。Alice 非常喜欢这些糖,她想要在遵循医生建议的情况下,尽可能吃到最多不同种类的糖。

给你一个长度为 n 的整数数组 candyType ,返回: Alice 在仅吃掉 n / 2 枚糖的情况下,可以吃到糖的最多种类数。

示例 1:

输入:candyType = [1,1,2,2,3,3]
输出:3
解释:Alice 只能吃 6 / 2 = 3 枚糖,由于只有 3 种糖,她可以每种吃一枚。

示例 2:

输入:candyType = [1,1,2,3]
输出:2
解释:Alice 只能吃 4 / 2 = 2 枚糖,不管她选择吃的种类是 [1,2]、[1,3] 还是 [2,3],她只能吃到两种不同类的糖。

示例 3:

输入:candyType = [6,6,6,6]
输出:1
解释:Alice 只能吃 4 / 2 = 2 枚糖,尽管她能吃 2 枚,但只能吃到 1 种糖。

提示:

n == candyType.length
2 <= n <= 10^4
n 是一个偶数
-10^5 <= candyType[i] <= 10^5

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/distribute-candies
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

统计种类,如果种类大于一半,那么只能分一半不同的糖,否则就是分种类数的糖

class Solution {
    public int distributeCandies(int[] candyType) {
        int type = 0;
        int n = candyType.length;
        Set<Integer> set = new HashSet<>();
        for(int i = 0; i < n; i++){
            set.add(candyType[i]);
        }
        int l = set.size();
        if(l < n / 2)
            return l;
        else
            return n / 2;
    }
}

237. 删除链表中的节点

2021.11.02 每日一题

题目描述

请编写一个函数,用于 删除单链表中某个特定节点 。在设计函数时需要注意,你无法访问链表的头节点 head ,只能直接访问 要被删除的节点 。

题目数据保证需要删除的节点 不是末尾节点 。

示例 1:


输入:head = [4,5,1,9], node = 5
输出:[4,1,9]
解释:指定链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9

示例 2:


输入:head = [4,5,1,9], node = 1
输出:[4,5,9]
解释:指定链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9

示例 3:

输入:head = [1,2,3,4], node = 3
输出:[1,2,4]

示例 4:

输入:head = [0,1], node = 0
输出:[1]

示例 5:

输入:head = [-3,5,-99], node = -3
输出:[5,-99]

提示:

链表中节点的数目范围是 [2, 1000]
-1000 <= Node.val <= 1000
链表中每个节点的值都是唯一的
需要删除的节点 node 是 链表中的一个有效节点 ,且 不是末尾节点

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/delete-node-in-a-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

删除单向链表的结点,就是使前一个结点的指针改变指向,但是发现这里没有给前一个结点,那么怎么删除呢
只能是通过复制,将后一个结点的值复制到当前结点,然后使当前结点的指针指向后一个结点的后一个结点
相当于删除了下一个结点

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public void deleteNode(ListNode node) {
        //给我整不会了
        //只能复制了?
        node.val = node.next.val;
        node.next = node.next.next;
    }
}

407. 接雨水 II

2021.11.03 每日一题

题目描述

给你一个 m x n 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。

示例 1:


输入: heightMap = [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]
输出: 4
解释: 下雨后,雨水将会被上图蓝色的方块中。总的接雨水量为1+2+1=4。

示例 2:


输入: heightMap = [[3,3,3,3,3],[3,2,2,2,3],[3,2,1,2,3],[3,2,2,2,3],[3,3,3,3,3]]
输出: 10

提示:

m == heightMap.length
n == heightMap[i].length
1 <= m, n <= 200
0 <= heightMap[i][j] <= 2 * 10^4

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

这个确实难了
先回顾一下经典问题,接雨水,也就是二维的情况,有好几种解法
看一个位置能存储多少水就是看这个位置左右两端的最高高度,所以统计一个位置左右两端的最高高度,较小值减去当前位置高度就是能存储的水量
或者用单调栈,单调递减,栈中存储下标,如果比栈顶大了,那么就说明栈顶能存水了,就计算栈顶的存水量
或者还可以按行求

那么换成三维的应该怎么做呢
依然是相同的思路,一个位置可以存水量,也是看它的周围,但是和二维不同的是,如果上下左右有比它高的,但是也有比它低的,水有可能会流出去,所以需要维护的是一个圈
所以这里先确定四周,四个边界是不可能存水的,所以高度是确定的
然后再找到边界上高度最低的点,那么依据木桶原理,这个位置周围的存水量可以计算,具体配图看官解,很清晰

class Solution {
    public int trapRainWater(int[][] heightMap) {
        //咋做呢,半年前还做过
        //依据二维的做法,看每个位置前后左右的高度吗
        //首先看四个边界的格子,它们是不可能存水的,所以将他们的信息(x,y,h)放入优先队列中
        //这就相当于给中间的所有格子框定了一个范围,存储的水量是不可能超过这个范围的
        //然后开始弹出队列顶端的元素,即高度最小的值
        //然后去遍历这个位置的四周,如果有比它还小的高度,那么说明这个高度可以存水,并且将存水后的高度放入队列中
        //如果没有比它小的高度,也放入队列中
        //当所有位置都遍历完,就可以得到答案
        int m = heightMap.length;
        int n = heightMap[0].length;
        int[][] dir = {{0,1}, {0,-1}, {1,0}, {-1,0}};
        PriorityQueue<int[]> pq = new PriorityQueue<>((a,b) ->(a[2] - b[2]));
        boolean[][] used = new boolean[m][n];
        //放周围元素
        for(int i = 0; i < m; i++){
            pq.offer(new int[]{i, 0, heightMap[i][0]});
            pq.offer(new int[]{i, n - 1, heightMap[i][n - 1]});
            used[i][0] = true;
            used[i][n - 1] = true;
        }
        for(int i = 1; i < n - 1; i++){
            pq.offer(new int[]{0, i, heightMap[0][i]});
            pq.offer(new int[]{m - 1, i, heightMap[m - 1][i]});
            used[0][i] = true;
            used[m - 1][i] = true;
        }
        int res = 0;
        //然后处理优先队列
        while(!pq.isEmpty()){
            int[] top = pq.poll();
            int x = top[0];
            int y = top[1];
            int h = top[2];
            for(int i = 0; i < 4; i++){
                int nx = x + dir[i][0];
                int ny = y + dir[i][1];
                if(nx >= 0 && nx < m && ny >= 0 && ny < n && !used[nx][ny]){
                    used[nx][ny] = true;
                    if(heightMap[nx][ny] < h){
                        res += h - heightMap[nx][ny];
                        pq.offer(new int[]{nx, ny, h});
                    }else{
                        pq.offer(new int[]{nx, ny, heightMap[nx][ny]});
                    }
                }
            }
        }
        return res;
    }
}

以上是关于LeetCode 575. 分糖果 / 237. 删除链表中的节点 / 407. 接雨水 II的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 575 分糖果[set] HERODING的LeetCode之路

LeetCode 575. 分糖果

leetcode打卡——去重之575. 分糖果

575. 分糖果『简单』

575. 分糖果思维

解题报告Leecode. 575. 分糖果——Leecode每日一题系列