leetcode 热题 100(部分)C/C++

leetcode 热题 100

双指针

盛最多水的容器 【mid】【双指针】

在这里插入图片描述
思路:
好久没写代码sb了,加上之前写的双指针并不多,以及有点思维定势了。我对双指针比较刻板的印象一直是两层for循环i,j,初始时i,j都位于左界附近,但是对于第i次的内层循环,j只需要从第i-1次内层循环停下时的j开始循环,即内层的循环变量j一直在增加,而不会减少,故双指针复杂度O(n)
然鹅,本题利用双指针l,r,初始分别位于左界和右界,之后++l--r,这样子移动。
至于如何移动,写出容器容量公式便很容易想出V=(r - l - 1) * min(height[l], height[r])。为取得Vmax,考虑无论移动l or r,都会使得宽d = r - l - 1 变小,故考虑如何使得min(height[l], height[r])变大,容易发现应该移动height小的那一个。
AC代码

class Solution {
public:
    int maxArea(vector<int>& height) {
        int n = height.size();
        int l = 0, r = n - 1;
        int s = (r - l) * min(height[l], height[r]);
        int res = s;
        while(l < r)
        {
            if(height[l] < height[r]) ++l;
            else --r;
            s = (r - l) * min(height[l], height[r]);
            res = max(res, s);
        }
        return res;
    }
};

三数之和 【mid】【双指针】

在这里插入图片描述
思路:
与上一题类似。
先排序,之后搜一遍。
对于nums[i],需要从右边找出两个数字使得和为-nums[i]
双指针l,r初始分别为左界和右界,据nums[l] + nums[r]-nums[i]的大小关系决定移动哪个指针即可。
另外对于去重,可直接通过set逃课。
AC代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> res;
        set<vector<int>> st;
        sort(nums.begin(), nums.end());

        int a, sum, last = -5000000;
        int l, r;
        bool flag;
        for(int i = 0; i < n; ++i)
        {
            if(nums[i] == last) continue;
            else
            {
                last = nums[i];
                l = i + 1; 
                r = n - 1;
                a = -nums[i];
                while(l < r)
                {
                    sum = nums[l] + nums[r];
                    if(sum > a) --r;
                    else if(sum < a) ++l;
                    else 
                    {
                        vector<int> vt;
                        vt.push_back(nums[i]);
                        vt.push_back(nums[l]);
                        vt.push_back(nums[r]);
                        st.insert(vt);
                        ++l;
                    }
                }
            }
        }
        for(auto x : st) res.push_back(x);
        return res;
    }
};

接雨水【hard】【双指针/单调栈】

在这里插入图片描述
思路:
【解1】:预处理(对应官方题解dp解法)
考虑每个洼地可容纳的雨水,取决于这个洼地左侧和右侧的最高的高地的较小值。对于每个洼地左侧和右侧的最高的高地,预处理即可。
【解2】:双指针
思路同解1,只不过不做预处理,而是用双指针l,r初始分别为左界右界,移动过程中,分别维护扫过区域的最大值,每次移动最大值较小的那一侧,然后判断移动之后是洼地还是高地,洼地则计算接的雨水,高地则更新单侧最大值。
关于为什么移动最大值较小的那一侧,假设较高的一侧是r
移动r侧,由于移动之后可能是高地or洼地,对于高地,不计算贡献,其实无所谓,但是对于洼地,需要计算贡献,此时贡献取决于洼地两侧最高的高地的较小值,然而左侧最高的高地其实是不确定的,故无法计算。倘若移动是l的一侧,虽然右侧最高的高地也是不确定的,但至少可以确定的是右侧的高地一定比左侧的高,故可以计算正确的贡献。
【解3】:单调栈
构造一个单减栈(栈底>栈顶)。对于单调栈,其实每个元素都会进栈一次。
对于遍历到的当前元素,若<栈顶元素,入栈
否则,说明存在可以积水的洼地,此时需要弹出栈顶元素,可积的雨水取决于洼地的宽度(据两侧高地的距离)及可积雨水的高地,循环处理,直至当前元素可以入栈。(此过程官方视频题解动画容易理解)。
AC代码:
预处理:

class Solution {
public:
    int trap(vector<int>& height) {
        
        int n = height.size();
        int res = 0;
        int lmx[n + 5], rmx[n + 5];
        lmx[0] = height[0], rmx[n - 1] = height[n - 1];

        for(int i = 1; i < n; ++i) lmx[i] = max(lmx[i - 1], height[i]);
        for(int i = n - 2; i >= 0; --i) rmx[i] = max(rmx[i + 1], height[i]); 

        int mx1, mx2, h;
        for(int i = 0; i < n; ++i)
        {
            mx1 = lmx[i], mx2 = rmx[i];
            h = min(mx1, mx2);
            res += (h - height[i]);
        }

        return res;
    }
};

双指针:

class Solution {
public:
    int trap(vector<int>& height) {
        
        int n = height.size();
        int res = 0;
        int l = 0, r = n - 1;
        int lmx = height[0], rmx = height[n - 1];
        
        while(l < r)
        {
            if(lmx < rmx)
            {
                ++l;
                if(lmx > height[l]) res += lmx - height[l];
                else lmx = height[l];
            }
            else
            {
                --r;
                if(rmx > height[r]) res += rmx - height[r];
                else rmx = height[r];
            }
        }

        return res;
    }
};

单调栈:

class Solution {
public:
    int trap(vector<int>& height) {
        
        stack<int> st;
        int n = height.size();
        int res = 0;
        
        for(int i = 0; i < n; ++i)
        {
            while(!st.empty() && height[i] > height[st.top()])
            {
                int tp = st.top();
                st.pop();
                if(st.empty()) break;
                int l = st.top();
                int d = i - l - 1;
                int h = min(height[l], height[i]) - height[tp];
                res += d * h;
            }
            st.push(i);
        }

        return res;
    }
};

子串

最小覆盖字串【hard】【双指针/滑动窗口】

在这里插入图片描述
思路:
先找出左边界为字符串s的左边界且能覆盖t的最小子串。
之后,利用双指针/滑动窗口的思想,交替移动左右指针l,r
具体规则如下:
若当前子串能够覆盖,则++l,否则++r,每次移动后判断新的子串是否能够覆盖并且是否变小,保存最小能覆盖的子串长度以及其左右边界l,r
关于如何判断,只需在移动的过程中维护好如下容器or变量便显而易见。

map<char, int> mp; 			  //hash,'a'~'z'对应1~26,'A'~'Z'对应27~52
int cnt_s[64]				  //cnt_s[i]表示当前子串s[l~r]中i对应的字母个数,cnt_t[i]表示
int cnt_t[64];				  //cnt_t[i]表示t串中i对应的字母一共有几个
int num = 0, cnt = 0;		  //num表示t串一共有多少个不同的字母,cnt表示当前子串s[l~r]已经覆盖了t中的字母个数
int l, r;					  //当前正在处理的子串s[l~r]
int min_l, min_r, mi = inf;   //目前所有处理的子串中能覆盖的最小子串的左右边界及长度

AC代码:

class Solution {
public:
    string minWindow(string s, string t) {

        const int inf = 0x3f3f3f3f;
        int len1 = s.size(), len2 = t.size();
        map<char, int> mp;
        int cnt_s[64], cnt_t[64];
        int num = 0, cnt = 0;
        int l, r, min_l = 0, min_r = 0, mi = inf; 
        string str;
        
        for(char ch = 'a'; ch <= 'z'; ++ch) mp[ch] = ch - 'a' + 1;
        for(char ch = 'A'; ch <= 'Z'; ++ch) mp[ch] = ch - 'A' + 1 + 26;

        for(int i = 0; i < len2; ++i) ++cnt_t[mp[t[i]]];
        for(int i = 1; i < 55; ++i) if(cnt_t[i]) ++num;
        
        l = 0, r = -1;
        while(r < len1)
        {
            if(cnt == num)
            {
                if(cnt_s[mp[s[l]]] == cnt_t[mp[s[l]]]) --cnt;
                --cnt_s[mp[s[l++]]];
            }
            else
            {
                ++cnt_s[mp[s[++r]]];
                if(cnt_s[mp[s[r]]] == cnt_t[mp[s[r]]]) ++cnt;
            }

            if(cnt == num && r - l + 1 < mi)
            {
                mi = r - l + 1;
                min_l = l, min_r = r;
            } 
        }

        if(mi == inf) return "";
        else 
        {
            str = s.substr(min_l, mi);
            return str;
        }
    }
};

普通数组

轮转数组【mid】【数论/gcd】

在这里插入图片描述
思路
给出空间O(1),且不用reverse的方法。(官方题解推导比较清楚)。
维护两个变量postmp,分别表示现在的位置和对应位置上的值,由此,更新只需pos = (pos + k) % n,swap(nums[pos], tmp),当pos回到最开始的位置时,我们称这是完成了一趟修改,此时应该停下,然鹅有的元素并没有遍历到。(只将下标为gcd(k,n)的元素遍历了,可证,另见类似题目,2015ICPC沈阳,跳青蛙🐸容斥),故需要将pos+1,再依次为开始,继续上述操作,直至回到开始位置并遍历全部位置。
接下来考虑需要几趟(根据上面结论,其实可知需要gcd(n,k)趟)。假设转了a圈,遍历了b个元素,则an=bk,故an一定是n,k的倍数,又因为我们在第一次回到起点时便结束了,故a应尽可能的小,由此an=lcm(n,k),故b=lcm(n,k)/k,即需要遍历的趟数cnt=n/b=gcd(n,k)
AC代码:

class Solution {
public:

    int gcd(int a, int b)
    {
        return b == 0 ? a : gcd(b, a % b);
    }

    void rotate(vector<int>& nums, int k) {
    
        int n = nums.size();
        k %= n;
        int cnt = gcd(n, k);

        for(int i = 0; i < cnt; ++i)
        {
            int pos = i;
            int tmp = nums[i];
            while(true)
            {
                pos = (pos + k) % n;
                swap(nums[pos], tmp);
                if(pos == i) break;
            }
        }
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/507543.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

集成百兆,千兆,万兆网络变压器等电子元器件的RJ45 Jack连接器在屏显控制系统中的应用

Hqst华轩盛(石门盈盛)电子导读&#xff1a;集成百兆&#xff0c;千兆&#xff0c;万兆网络变压器等电子元器件的RJ45 Jack连接器在屏显控制系统中的应用 一 ﹑集成百兆&#xff0c;千兆&#xff0c;万兆网络变压器等电子元器件的RJ45 Jack连接器在屏显控制系统中的应用前景 近年…

《Slime War: Idle Hero》

Slime War: Idle Hero 类型&#xff1a;Idle Arks 模拟经营 视角&#xff1a;2d 乐趣点&#xff1a;卡牌收集&#xff0c;战斗成长&#xff0c;家园建造&#xff0c;英雄培养 时间&#xff1a;2023-2024 个人职责&#xff1a; 1、参与原生DEMO研发制作 2、主导基础框架的讨论…

非关系型数据库之Redis配置与优化

一、关系数据库与非关系型数据库 1.1关系型数据库 关系型数据库是一个结构化的数据库&#xff0c;创建在关系模型&#xff08;二维表格模型&#xff09;基础上一般面向于记录。SQL语句&#xff08;标准数据查询语言&#xff09;就是一种基于关系型数据库的语言&#xff0c;用…

OpenHarmony实战:RK3568 开发板镜像烧录指南

前言 烧录开发板是每个开发者的必修课&#xff0c;每次对系统的修改务必进行烧录测试&#xff0c;确保修改正确和不会引入新问题。 本文基于 Windows10&#xff0c;以 RK3568 开发板为例&#xff0c;指导如何烧录 OpenHarmony 镜像&#xff0c;镜像也叫固件。Hihoop&#xff…

如何制作CG动画?渲染农场在其中扮演的角色是什么?

CG动画制作是一个融合了艺术与技术的综合流程&#xff0c;从初步的概念设计延伸至最终成品。在这一过程中&#xff0c;渲染农场扮演着核心角色&#xff0c;它通过提供充足的计算能力来加快动画的渲染速度&#xff0c;从而确保创作团队能够以高效率制作出优质的动画作品。 一、c…

京东云免费服务器申请入口,2024年最新免费云主机

京东云服务器免费6月申请入口 jdyfwq.com 在京东云免费云主机申请页面&#xff0c;免费云服务器配置为云主机2核4G5M和轻量云主机2C2G可以申请免费使用&#xff0c;目前京东云免费云服务器申请时长从之前的6个月缩短到1个月&#xff0c;如下图&#xff1a; 京东云免费云主机 云…

[Windows]服务注册工具(nssm)

文章目录 官网下载地址百度云下载地址NSSM常用命令 使用场景&#xff1a;例如现在我们想开启自动启动一个Java服务,nginx,node等。 官网下载地址 https://nssm.cc/download 百度云下载地址 链接&#xff1a;https://pan.baidu.com/s/111fkBWIS7CTlWIj80Kc8Sg?pwdanan 提取码…

【二叉树】Leetcode 114. 二叉树展开为链表【中等】

二叉树展开为链表 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同…

中间系统-度量值、主机名映射、收敛特性、区域迁移、多拓扑

中间系统-度量值&#xff0c;主机名映射&#xff0c;收敛特性 1、ISIS度量值 ISIS Cost计算&#xff1a;一个接口的cost固定等于10. ISIS的Cost值范围为1~63&#xff08;称为IS-IS开销类型为narrow窄度量&#xff09;&#xff0c;不够使用只能做扩展&#xff08;宽度量&…

SwiftUI Swift 选择图片 添加图片

1. 添加记帐时添加图片功能 2. Show me the code // // TestPhotoPicker.swift // pandabill // // Created by 朱洪苇 on 2024/3/30. //import SwiftUI import PhotosUI import Foundationstruct TestPhotoPicker: View {State private var selectedItem: PhotosPickerIt…

机器学习在智能音箱中的应用探索与实践:让声音更懂你

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

多微信聚合聊天神器,让你的社交更高效!

对于那些拥有多个微信号的用户来说&#xff0c;频繁地在不同微信号和设备之间切换既麻烦又容易搞混。这时候&#xff0c;一款多微信聚合聊天神器——微信管理系统应运而生&#xff0c;为我们带来了极大的便利与高效。 下面一起来看看它都有哪些功能吧&#xff01; 1、多微信同…

Google Chrome将某个页签静音,不是网站

Google Chrome将某个页签静音&#xff0c;不是网站 打开chrome://flags/在里面搜索&#xff0c;audio&#xff0c;找到Tab audio muting UI contorl的选项&#xff0c;右侧设置为Enable。重新启动浏览器。 发现有声音的浏览器页签有一个喇叭图标&#xff0c;点击一下就行了。

【游戏分析】FPS游戏狩猎百发百中

某某游戏狩猎玩法及其类似于FPS游戏 即3D射击 所以同样拥有 自动瞄准功能和爆头功能 想达到百发百中我们就要精准的计算出3D朝向值 读取人物坐标 遍历怪物,读取怪物坐标比较简单,不过多陈诉 朝向自然而然一定是我们和敌人的坐标计算出来的 那么怎么计算的呢&#xff1f; 我…

web安全学习笔记【21】——安全开发

安全开发-PHP应用&留言板功能&超全局变量&数据库操作&第三方插件引用 #知识点&#xff1a; 1、PHP留言板前后端功能实现 2、数据库创建&架构&增删改查 3、内置超全局变量&HTML&JS混编 4、第三方应用插件&传参&对象调用 DAY1 #章…

Shopee,lazada如何实施稳定的测评,补单自养号方案,关键的步骤和条件

随着平台竞争激烈&#xff0c;越来越多的商家对常规运营也是力不从心。传统的广告和营销方式已经无法满足商家的需求&#xff0c;因此自养号测评也成为商家重要的推广方式。实现自养号测评&#xff0c;补单所需的技术条件。 1.不同账户的独立运行环境和阻断平台检测非常重要。稳…

判断点在多边形内的算法

在计算几何中&#xff0c;判定点是否在多边形内&#xff0c;是个非常有趣的问题。通常有两种方法&#xff1a; 一、Crossing Number&#xff08;交叉数&#xff09; 它计算从点P开始的射线穿过多边形边界的次数。当“交叉数”是偶数时&#xff0c;点在外面;当它是奇数时&…

花大钱办小事,游戏厂商为何开始打造奢华版副游?

3月28日&#xff0c;网易号称耗时6年、花费10亿研发的年度重磅MMO产品《射雕》上线。 对比同样在三月份腾讯开放测试的MMO游戏《塔瑞斯世界》&#xff0c;会发现很有意思的一幕&#xff1a;相比《塔瑞斯世界》想要打造手游版“魔兽世界”&#xff0c;不断完善养成体系想要把玩…

应急响应靶机训练-Linux1题解

前言 接上文&#xff0c;应急响应靶机训练Linux1 靶机地址&#xff1a; 应急响应靶机-Linux(1) 最近感冒了&#xff0c;就没录视频版。 题解 目标&#xff1a;3个flag以及黑客的ip地址 登陆虚拟机 密码defend flag1: su history flag{thisismybaby} flag2&#xff1a;…