【水滴计划 | 每日两题】:盛最多水的容器、移除元素

105 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情

1、写在前面

大家好,我是翼同学,这里是【水滴计划 | 刷题日志】

每日两题,拒绝摆烂。

2、内容

2.1、题目一:盛最多水的容器

链接:11. 盛最多水的容器 - 力扣(LeetCode)

(1) 描述

image.png

(2) 举例

image.png

image.png

(3) 解题

这道题的解题思路在于,最大面积取决于短板

首先我们定义双指针leftright,分别指向水槽的左右两端,如下所示:

int left = 0;
int right = height.size() - 1;

水槽的面积公式为: S=min(height[i],height[j])(ji)S = min(height[i], height[j]) * (j-i)

为什么说最大面积取决于短板呢?

我们定义双指针后,定义循环条件为left<right,即如果双指针相遇则退出循环。在每次循环中,都会将短板向内移动一格,移动之后虽然底部边长-1,但是高度可能会增大,因此下一个水槽的面积或许会增大。

但为什么不让长板向内移动呢?这是因为,将长板向内移动,即使遇到更长的板,此时水槽的面积也受限于短板,使得面积不可能变大,只会变小。因此,要使水槽面积有变大的可能,只能让短板往内移动。

因此代码如下:

class Solution {
public:
    int maxArea(vector<int>& height) {
        // 1. 定义双指针 left 和 right
        int left = 0;
        int right = height.size() - 1;
        // 2. 定义一个变量表示最大面积
        int maxArea = 0;
        // 3. 循环遍历数组
        while(left < right) {
            // 3.1 如果左板较小,则将左板向右移动
            if(height[left] < height[right]) {
                // 更新最大面积的值
                maxArea = max(maxArea, (right - left) * height[left]);
                left++;
            } 
            // 3.2 否则将右板向左移动
            else {
                // 更新最大面积的值
                maxArea = max(maxArea, (right - left) * height[right]);
                right--;
            }                 
        }
        // 4. 返回结果
        return maxArea;
    }
};

image.png

2.2、题目二:移除元素

链接:27. 移除元素 - 力扣(LeetCode)

(1) 描述

image.png

image.png

(2) 举例

image.png

image.png

image.png

(3) 解题

首先,先暴力解法来一遍。(两层for循环)

代码如下:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        // 1. 拿到数组nums的大小 size
        int size = nums.size();
        // 2. 第一层循环遍历数组的每个元素
        for (int i = 0; i < size; i++) {
            // 2.1 如果发现了 移除元素 则将后面的值往前移一位
            if (nums[i] == val) { 
                // 2.2 第二层循环更新数组
                for (int j = i + 1; j < size; j++) {
                    nums[j - 1] = nums[j];
                }
                // 2.3 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
                i--;
                // 2.4 数组长度减一
                size--;
            }
        }
        // 3. 返回结果
        return size;

    }
};

image.png

另一种思路是双指针解法,具体如下所示:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        // 1. 定义指针left,寻找新数组的元素(新数组指的是不含 val 的数组)
        int left = 0;
        // 2. 另一个指针right用于遍历数组,指向更新 新数组 的下标位置
        for (int right = 0; right < nums.size(); right++) {
            // 3. 如果元素不等于val,则原地赋值给新数组
            if (nums[right] != val) {
                nums[left] = nums[right];
                left++;
            }
            //4. 当然如果等于val,则不管它,因为后面元素会覆盖掉它
        }
        // 5. 返回新数组的长度
        return left;
    }
};

image.png


3、写在最后

好了,今天就刷到这里,明天再来。