LeetCode 特训 ---- Week1

news2024/10/5 14:30:01

目录

LeetCode 特训 --- Week1

两数之和

最长回文子串

删除有序数组中的重复项

删除有序数组中的重复项Ⅱ

删除链表中的重复元素

移动0

旋转链表

分隔链表

快慢指针(前后指针)用的好,链表,数组起码轻松打十个。


LeetCode 特训 --- Week1

两数之和

力扣

img

解题思路

方式1:很明显我们可以利用记录前面走过的值,记忆化,的方式来查找前面是否有我们想要的值。每两个值的和都可能是target,当前遍历的值val, 如果前面走过的值中存在target - val,答案可得。

处置方式,前面使用一种快速查找的数据结构来维护我们已经遍历过的路径path. 每遍历新的值val,都从path中查询 (target - val).

hash,或者红黑树。。。来解决这一系列的问题,包括两数和以及三数和...

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> inds;
        for (int i = 0; i < nums.size(); i ++) {
            int distance = target - nums[i];
            //不是ans, 加入hash表中
            if (inds.empty() || inds.find(distance) == inds.end()) {
                inds[nums[i]] = i;
                continue;
            } 
            return {inds[distance], i};
        }
        return {-1, -1};
    }
};

方式2:很明显借助排序之后结果用左右指针遍历搜索也可以达到目的,反正只要存在答案,我们遍历所有可能成为答案的情况就一定可以找到结果。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        std::vector<int> copy_nums(nums.begin(), nums.end());
        std::sort(nums.begin(), nums.end()); //sort
        int l = 0, r = nums.size() - 1; //左右指针记录ans
        while (l < r) {
            if (nums[l] + nums[r] == target) {
                break;
            } else {
                if (nums[l] + nums[r] < target) {
                    l ++;
                } else {
                    r --;
                }
            }
        }
        if (l >= r) {
            return {-1, -1};
        }
        std::vector<int> ans;
        for (int i = 0; i < nums.size(); i ++) {
            if (copy_nums[i] == nums[l] 
            || copy_nums[i] == nums[r]) {
                ans.push_back(i);
            }
        }
        return ans;
    }
};

最长回文子串

力扣

 

解题思路:

1. 因为是子序列问题,不清楚边界,方式1,在每一个位置都可能是结果,从中间向两边自由扩散获取结果。(老哥给的经验,边界不明确的问题,可以直接的进行一个一点点的扩大,一点点的从中间向两边扩散找边界)

//边界问题是写双指针最应该注意的.
class Solution {
    //寻找以lbegin, rbegin左右扩散的最长回文子串
    std::string subPalindrome(std::string& s, int lbegin, int rbegin) {
        int l = lbegin, r = rbegin, n = s.size();
        while (l >= 0 && r < n && s[l] == s[r]) {
            l --, r ++;
        }
        //l位置不可取 【l+1, r-1】区间元素个数(r-1-l-1+1) = (r-l-1)个
        return s.substr(l + 1, r - l - 1);
    }
public:
    string longestPalindrome(string s) {
        std::string ans = "";
        for (int i = 0; i < s.size(); i++) {
            std::string s1 = subPalindrome(s, i, i);//奇数串 
            std::string s2 = subPalindrome(s, i, i + 1);//偶数串
            ans = ans.size() >= s1.size() ? ans : s1; 
            ans = ans.size() >= s2.size() ? ans : s2; 
            //std::cout << ans << std::endl;
        }
       return ans;
    }
};

2. 可以使用动态规划,记忆化搜索的方式,用空间来提高效率。

删除有序数组中的重复项

力扣力扣 

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int last = 0, front = 0;
        while (front < nums.size()) {
            if (nums[last] != nums[front]) {   //非重复, 符合题意的值,放入slow结果序列
                nums[++last] = nums[front]; 
            }
            front ++;                          //前指针继续向前探路,寻求非重复值
        }
        return last + 1;
    }
};

删除有序数组中的重复项Ⅱ

力扣

核心思路还是前后(快慢)指针,只不过中间需要维护一个计数器

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int last = 0, front = 0, n = nums.size();
        int count = 0;
        int preval = nums[0];       //记录前面的遍历值
        while (front < n) {
            if (nums[front] != preval) {//一个子序列值遍历完毕
                count = 0;
                preval = nums[front];
            }
            if (count < 2) {
                nums[last++] = nums[front];
            }
            front ++;           //向后寻求符合要求的值,
            count ++;           //计数
        }
        return last;
    }
};

删除链表中的重复元素

力扣

解题思路还是哪个思路,向后寻找非重复元素链接到前面去就OK了。 前面的p指针相当于是做数组题目时候的last指针,维护着结果序列

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if (head == nullptr) return nullptr;
        ListNode* last = head, *front = head;
        while (front) {
            if (last->val != front->val) {  //非重复值,留下来.
                last->next = front;
                last = last->next;
            }
            front = front->next;  //向前探路
        }
        last->next = nullptr;
        return head;
    }
};
​

移动0

力扣

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int last = 0, front = 0, n = nums.size();
        while (front < n) {
            if (nums[front] != 0) {     //寻求到非零数字, 放到last结果序列中
                nums[last++] = nums[front];
            } 
            front ++;                   //向后寻求非零数字
        }
        //将后续制0
        while (last < n) {
            nums[last++] = 0;
        }
    }
};

快慢指针,前后指针的核心思想在那里?

慢指针停留在后面,保留的是最终结果,快指针跑在前面探路,寻找的是可以留下来当作结果的值。(符合题意,需要留下的值)

旋转链表

力扣

思路:很明显,右边移动几个位置,相当于是头结点换成了右边的第k%num个结点。所以很自然的可以想到先成环,再断开。链表的操作注意头部结点和边界问题。

class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if (head == nullptr) { return nullptr; }
        int cnt = 1;
        ListNode* p = head;
        while (p->next) {//计算元素个数并且p走到尽头
            cnt ++;
            p = p->next;
        }
        p->next = head;//成环
        k %= cnt;
        // 走到cnt-k节点处断开
        int n = cnt - k; 
        p = head;
        while (--n) {
            p = p->next;
        }
        ListNode* ans = p->next;
        p->next = nullptr;
        return ans;
    }
};

分隔链表

力扣 

思路:很明显的按照题意走即可。遍历原链表拆成两个部分的子链表,然后两个子链表连起来就OK了。还是需要注意边界,结束位置要有nullptr,链表的题目往往难度不在思维,在乎对于指针的控制,以及边界的顾及。

class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        if (head == nullptr) { return nullptr; }
        ListNode h1, h2, *t1, *t2;//记录两条链表的头尾
        t1 = &h1, t2 = &h2;
        ListNode *p = head; 
        while (p) {
            if (p->val < x) {
                t1->next = p;
                t1 = t1->next;
            } else {
                t2->next = p;
                t2 = t2->next;
            }
            p = p->next;
        }
        t1->next = h2.next;//中间衔接
        t2->next = nullptr;//末尾制空,否则死循环了 细节。。。
        return h1.next;
    }
};

快慢指针(前后指针)用的好,链表,数组起码轻松打十个。

快慢指针真好用,快指针(前指针)跑在前面探路,做个侦察小兵,寻找符合题目要求的结点或者值,慢指针维护结果序列,存储快指针找到的一系列符合题目要求的值。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

videoPictureInPicture,视频画中画播放初探

从Chrome 70版本开始video元素开始支持画中画播放&#xff0c;简单写个demo体验一下 简介 在触发画中画之后视频会始终在右下角悬浮&#xff0c;不论是否在当前标签页或者是浏览器是否最小化。 可以在chrome内看任意视频时点击控制条的画中画按钮即可。 API 文档&#xff1…

人工智能机器人技术概述

移动机器人是一种能够在其环境中移动的自主或半自主机器人系统&#xff0c;通常是通过轮子或履带进行移动。这些机器人旨在在各种环境中执行各种任务&#xff0c;包括探索、监视、检查、运输和操作&#xff0c;包括室内和室外空间、危险区域甚至其他星球。 移动机器人配备传感…

日常记录:天梯赛练习集L1-048 矩阵A乘以B

题目&#xff1a; 给定两个矩阵A和B&#xff0c;要求你计算它们的乘积矩阵AB。需要注意的是&#xff0c;只有规模匹配的矩阵才可以相乘。即若A有Ra​行、Ca​列&#xff0c;B有Rb​行、Cb​列&#xff0c;则只有Ca​与Rb​相等时&#xff0c;两个矩阵才能相乘。 输入格式&…

【JAVA-模块四 流程控制语句】

JAVA-模块四 流程控制语句一 选择分支语句&#xff1a;if语句if第一种格式&#xff1a;if第二种格式 双分支&#xff1a;if的第三种格式&#xff1a;多条件分支switch多分支&#xff1a;注意&#xff1a;if语句和swich语句如何选择&#xff1a;二 循环语句&#xff1a;2.1 for循…

聚焦弹性问题,杭州铭师堂的 Serverless 之路

作者&#xff1a;王彬、朱磊、史明伟 得益于互联网的发展&#xff0c;知识的传播有了新的载体&#xff0c;使用在线学习平台的学生规模逐年增长&#xff0c;越来越多学生在线上获取和使用学习资源&#xff0c;其中教育科技企业是比较独特的存在&#xff0c;他们担当的不仅仅是…

Mars3D集成到ruoyi管理系统

尽管Mars3d的官网上提供了详尽的文档和API参考手册&#xff0c;但是在集成至ruoyi后天管理系统中时&#xff0c;还是碰到了不少问题&#xff1a; npm安装方式&#xff0c;若只安装mars3d&#xff0c;会提示找不到mars3d-cesium引用cesium相关库的时候&#xff0c;报404错误 这…

MongoDB基础学习总结及SpringBoot项目中的整合

前言 MongoDB 如今是最流行的 NoSQL 数据库之一&#xff0c;被广泛应用于各行各业中&#xff0c;很多创业公司数据库选型就直接使用了 MongoDB。MongoDB一经推出就受到了广大社区的热爱&#xff0c;可以说是对程序员最友好的一种数据库之一&#xff0c;下面主要是笔者在平常的…

大学刚毕业,用10000小时,走进字节跳动拿了offer

前言&#xff1a; 没有绝对的天才&#xff0c;只有持续不断的付出。对于我们每一个平凡人来说&#xff0c;改变命运只能依靠努力幸运&#xff0c;但如果你不够幸运&#xff0c;那就只能拉高努力的占比。 2020年7月&#xff0c;我有幸成为了字节跳动的一名测试开发&#xff0c…

IO流、多线程

FileInputStream FileOutputStream 原理&#xff1a; //1、创建一个FileOutputStream对象&#xff0c;构造方法中写入数据的目的地 FileOutStream fos new FileOutputStream("C:\\a.txt"); //2、调用FileOutputStream对象中的方法write&#xff0c;把数据写入文件中…

【微信小程序】关于实现自定义图片代替checkbox样式的记录

前言 checkbox很好使&#xff0c;使用中往往需要改变它的样式。 记录一下用自定义的图片代替原有样式的过程。 关于把checkbox从&#xff1a;变成的过程 正文 思路 问题拆分&#xff1a; ①如何修改checkbox的样式 ②如何使用图片代替原有样式 如何修改checkbox的样式 修…

氢原子的电子轨道半径、能量、速度

在https://blog.csdn.net/qq_35379989/article/details/130065868?spm1001.2014.3001.5501中我们已经给出了波尔模型的三大假设&#xff1a;定态假设、跃迁假设以及角动量量子化。 一、氢原子的轨道半径 在跃迁假设中&#xff0c;通过设定波尔模型轨道能量&#xff1a;与电子…

各种商业版本的ChatGPT已经推出了,还有必要搞个人的Chat吗?

一、引言 虽然市面上已经存在许多商业版本的ChatGPT交互产品&#xff0c;但在我们的开发中&#xff0c;决定专注于打造一个更加个性化、更贴合个人需求的智能助手。我们相信&#xff0c;每个人都是独一无二的&#xff0c;他们的需求也是各不相同的。因此&#xff0c;个人ChatG…

浅析PHP代码审计中的SQL注入漏洞

浅析PHP代码审计中的SQL注入漏洞1.概述2.普通注入3.编码注入宽字节注入二次urldecode注入4.漏洞防范gpc/rutime魔术引号过滤函数和类addslashes函数mysql_[real_]escape_string函数intval等字符转换PDO prepare预编译1.概述 SQL注入的攻击方式有下面几种&#xff1a; 在权限较…

常用电阻的作用

1、限流&#xff1a; 根据公式&#xff1a;I U / R&#xff1b;可知&#xff0c;电压固定的情况下&#xff0c;电阻越大&#xff0c;电流越小 常用于保护器件&#xff0c; 例如&#xff1a;MCU的输入输出信号线串联电阻&#xff0c;以避免电流过大&#xff0c;损坏元器件 …

快鲸scrm助力眼科机构提效客户运营,提升转化率

眼科机构普遍面临着以下几方面的业务挑战 &#xff08;1&#xff09;存在信任危机&#xff0c;用户决策周期长 眼睛是心灵的窗户&#xff0c;患者在对眼部治疗机构的选择上格外慎重&#xff0c;因而决策周期较长&#xff0c;眼科机构需要通过品牌建设、 IP 的打造、优质的产品…

SDL(2)-加载图片

加载BMP 1.使用SDL_init初始化SDL库 2.使用SDL_CreateWindow创建一个窗口 3.使用SDL_GetWindowSurface获取创建窗口的surface 4.使用SDL_LoadBMP加载一张BMP图片 5.使用SDL_BlitSurface将加载的bmp surface拷贝到窗口的surface 6.使用SDL_UpdateWindowSurface更新到窗口 …

【严重】vm2 <3.9.15 沙箱逃逸漏洞(CVE-2023-29017)

漏洞描述 vm2 是一个沙箱&#xff0c;用于在 Node.js 环境中运行不受信任的代码。宿主对象(Host objects)是指由 Node.js 的宿主环境提供的对象&#xff0c;例如全局对象、文件系统或网络请求等。 vm2 3.9.15之前版本中&#xff0c;当处理异步错误时未正确处理 Error.prepare…

中国大学哪家强?Python爬取排名榜,太棒啦(31)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 欢迎和猫妹一起&#xff0c;趣味学Python。 今日主题 如何用Python&#xff0c;抓取并分析2023中国大学排名数据。 用到的Python库有requests、bs4。 requests库 reque…

PixiJS 渲染优化

最近做在线CAD可视化与编辑&#xff0c;对前端的可视化渲染技术进行了选型&#xff0c;对于二维CAD来说一般用canvas就够了&#xff0c;但是canvas每一次平移&#xff0c;缩放&#xff0c;更新数据都需要重新计算渲染所有的图形数据&#xff0c;数据一多就显得非常卡。如果使用…

TCP和UDP在实际工作中的应用

前言 日常在网上浏览一些文章时都会看到一些介绍TCP和UDP的文章&#xff0c;每次都是草草浏览&#xff0c;而没有深入的去研究&#xff0c;这几天在做日志采集工具的时候恰好遇到一个问题&#xff0c;就是采集端将采集到的内容发送到服务端时这里采用的通信协议应该如何考量&a…