LeetCode高频算法刷题记录6

news2024/11/25 0:40:18

文章目录

  • 1. 编辑距离【困难】
    • 1.1 题目描述
    • 1.2 解题思路
    • 1.3 代码实现
  • 2. 寻找两个正序数组的中位数【困难】
    • 2.1 题目描述
    • 2.2 解题思路
    • 2.3 代码实现
  • 3. 合并区间【中等】
    • 3.1 题目描述
    • 3.2 解题思路
    • 3.3 代码实现
  • 4. 爬楼梯【简单】
    • 4.1 题目描述
    • 4.2 解题思路
    • 4.3 代码实现
  • 5. 排序链表【中等】
    • 5.1 题目描述
    • 5.2 解题思路
    • 5.3 代码实现

1. 编辑距离【困难】

题目链接:https://leetcode.cn/problems/edit-distance/
参考题解:https://leetcode.cn/problems/edit-distance/solution/bian-ji-ju-chi-by-leetcode-solution/

1.1 题目描述

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

示例1:

输入:word1 = “horse”, word2 = “ros”
输出:3
解释:
horse -> rorse (将 ‘h’ 替换为 ‘r’)
rorse -> rose (删除 ‘r’)
rose -> ros (删除 ‘e’)

示例2:

输入:word1 = “intention”, word2 = “execution”
输出:5
解释:
intention -> inention (删除 ‘t’)
inention -> enention (将 ‘i’ 替换为 ‘e’)
enention -> exention (将 ‘n’ 替换为 ‘x’)
exention -> exection (将 ‘n’ 替换为 ‘c’)
exection -> execution (插入 ‘u’)

提示:

  • 0 <= word1.length, word2.length <= 500
  • word1 和 word2 由小写英文字母组成

1.2 解题思路

两个字符串之间的所有转换都可以用 3 种形式来表示:把 word1 添加一个字符变成 word2 ;把 word2 添加一个字符变成 word1 ;把 word1 修改一个字符变成 word2 。

  • 如果 word1[0…i-1] 到 word2[0…j-1] 的变换需要消耗 k 步,那么 word1[0…i] 到 word2[0…j] 只需要把 word1[0…i-1] 变换到 word2[0…j-1],消耗 k 步;再把 word1[i] 改成 word2[j],就行了。如果 word1[i] == word2[j],什么也不用做,一共消耗 k 步,否则需要修改,一共消耗 k + 1 步。
  • 如果 word1[0…i-1] 到 word2[0…j] 的变换需要消耗 k 步,那么 word1[0…i] 到 word2[0…j] 先经过 k 步,把 word1[0…i-1] 变换到 word2[0…j],消耗掉 k 步,再把 word1[i] 删除,这样,word1[0…i] 就完全变成了 word2[0…j] 了。一共 k + 1 步。
  • 如果 word1[0…i] 到 word2[0…j-1] 的变换需要消耗 k 步,那么 word1[0…i] 到 word2[0…j] 先经过 k 步,把 word1[0…i] 变换成 word2[0…j-1],消耗掉 k 步,接下来,再插入一个字符 word2[j],那么 word1[0…i] 就完全变成了 word2[0…j] 了。一共 k + 1 步。

因此,word1[0…i] 变换成 word2[0…j] 主要有三种手段,用哪个消耗少,就用哪个。

1.3 代码实现

class Solution {
public:
    int minDistance(string word1, string word2) {
        int len1 = word1.length();
        int len2 = word2.length();
        vector<vector<int>> ans(len1 + 1, vector<int>(len2 + 1));
        for(int i = 0; i < len1 + 1; ++i) {
            for(int j = 0; j < len2 + 1; ++j) {
                if(!i)
                    ans[0][j] = j;
                else if(!j)
                    ans[i][0] = i;
                else {
                    int insert1 = ans[i][j - 1] + 1;
                    int insert2 = ans[i - 1][j] + 1;
                    int replace = ans[i - 1][j - 1];
                    if(word1[i - 1] != word2[j - 1])
                        replace += 1;
                    ans[i][j] = min(min(insert1, insert2), replace);
                }
            }
        }
        return ans[len1][len2];
    }
};

2. 寻找两个正序数组的中位数【困难】

题目链接:https://leetcode.cn/problems/median-of-two-sorted-arrays/
参考题解:https://leetcode.cn/problems/median-of-two-sorted-arrays/solution/xun-zhao-liang-ge-you-xu-shu-zu-de-zhong-wei-s-114/

2.1 题目描述

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数

算法的时间复杂度应该为 O(log (m+n)) 。

示例1:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2

示例2:

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

提示:

  • nums1.length == m
  • nums2.length == n
  • 0 <= m <= 1000
  • 0 <= n <= 1000
  • 1 <= m + n <= 2000
  • -10^6 <= nums1[i], nums2[i] <= 10^6

2.2 解题思路

这道题让我们求两个有序数组的中位数,而且限制了时间复杂度为 O(log (m+n)) ,看到这个时间复杂度,自然而然的想到了应该使用二分查找法来求解。那么回顾一下中位数的定义,如果某个有序数组长度是奇数,那么其中位数就是最中间那个,如果是偶数,那么就是最中间两个数字的平均值。这里对于两个有序数组也是一样的,假设两个有序数组的长度分别为 m 和 n ,由于两个数组长度之和 m+n 的奇偶不确定,因此需要分情况来讨论,对于奇数的情况,直接找到最中间的数即可,偶数的话需要求最中间两个数的平均值。为了简化代码,不分情况讨论,我们分别找第 (m+n+1) / 2 个,和 (m+n+2) / 2 个,然后求其平均值即可,这对奇偶数均适用。假如 m+n 为奇数的话,那么其实 (m+n+1) / 2 和 (m+n+2) / 2 的值相等,相当于两个相同的数字相加再除以 2 ,还是其本身。

这里需要定义一个函数来在两个有序数组中找到第 K 个元素,下面重点来看如何实现找到第 K 个元素。首先,为了避免产生新的数组从而增加时间复杂度,我们使用两个变量i和j分别来标记数组 nums1 和 nums2 的起始位置。然后来处理一些边界问题,比如当某一个数组的起始位置大于等于其数组长度时,说明其所有数字均已经被淘汰了,相当于一个空数组了,那么实际上就变成了在另一个数组中找数字,直接就可以找出来了。还有就是如果 K = 1 的话,那么我们只要比较 nums1 和 nums2 的起始位置i和j上的数字就可以了。难点就在于一般的情况怎么处理?因为我们需要在两个有序数组中找到第 K 个元素,为了加快搜索的速度,我们要使用二分法,对 K 二分,意思是我们需要分别在 nums1 和 nums2 中查找第 K / 2 个元素,注意这里由于两个数组的长度不定,所以有可能某个数组没有第 K / 2 个数字,所以我们需要先检查一下,数组中到底存不存在第 K / 2 个数字,如果存在就取出来,否则就赋值上一个整型最大值。如果某个数组没有第 K / 2 个数字,那么我们就淘汰另一个数字的前 K / 2 个数字即可。有没有可能两个数组都不存在第 K / 2 个数字呢,这道题里是不可能的,因为我们的 K 不是任意给的,而是给的 m+n 的中间值,所以必定至少会有一个数组是存在第 K / 2 个数字的。最后就是二分法的核心啦,比较这两个数组的第 K / 2 小的数字 midVal1 和 midVal2 的大小,如果第一个数组的第 K / 2 个数字小的话,那么说明我们要找的数字肯定不在 nums1 中的前 K / 2 个数字,所以我们可以将其淘汰,将 nums1 的起始位置向后移动 K / 2 个,并且此时的K也自减去 K / 2 ,调用递归。反之,我们淘汰 nums2 中的前 K / 2 个数字,并将 nums2 的起始位置向后移动 K / 2 个,并且此时的 K 也自减去 K / 2 ,调用递归即可。

2.3 代码实现

class Solution {
public:
    double findKSortedArrays(vector<int>& nums1, int start1, vector<int>& nums2, int start2, int k) {
        int len1 = nums1.size();
        int len2 = nums2.size();
        if(start1 >= len1)
            return nums2[start2 + k - 1];
        if(start2 >= len2)
            return nums1[start1 + k - 1];
        if(k == 1)
            return min(nums1[start1], nums2[start2]);
        int mid1 = (start1 + k / 2 - 1 < len1) ? nums1[start1 + k / 2 - 1] : INT_MAX;
        int mid2 = (start2 + k / 2 - 1 < len2) ? nums2[start2 + k / 2 - 1] : INT_MAX;
        if(mid1 < mid2)
            return findKSortedArrays(nums1, start1 + k / 2, nums2, start2, k - k / 2);
        else {
            return findKSortedArrays(nums1, start1, nums2, start2 + k / 2, k - k / 2);
        }
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size();
        int len2 = nums2.size();
        int k1 = (len1 + len2 + 1) / 2;
        int k2 = (len1 + len2 + 2) / 2;
        return (findKSortedArrays(nums1, 0, nums2, 0, k1) + findKSortedArrays(nums1, 0, nums2, 0, k2)) / 2.0;
    }
};

3. 合并区间【中等】

题目链接:https://leetcode.cn/problems/merge-intervals/
参考题解:https://leetcode.cn/problems/merge-intervals/solution/he-bing-qu-jian-by-leetcode-solution/

3.1 题目描述

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间

示例1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

提示:

  • 1 <= intervals.length <= 10^4
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 10^4

3.2 解题思路

如果按照区间的左端点排序,那么在排完序的列表中,可以合并的区间一定是连续的。首先,将列表中的区间按照左端点升序排序。然后将第一个区间加入 merged 数组中,并按顺序依次考虑之后的每个区间:如果当前区间的左端点在数组 merged 中最后一个区间的右端点之后,那么它们不会重合,可以直接将这个区间加入数组 merged 的末尾;否则,它们重合,需要用当前区间的右端点更新数组 merged 中最后一个区间的右端点,将其置为二者的较大值。

3.3 代码实现

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end());
        int len = intervals.size();
        vector<vector<int>> ans;
        ans.push_back(intervals[0]);
        for(int i = 1; i < len; ++i) {
            int start = intervals[i][0];
            int end = intervals[i][1];
            if(start > ans.back()[1])
                ans.push_back(intervals[i]);
            else {
                ans.back()[1] = max(ans.back()[1], end);
            }
        }
        return ans;
    }
};

4. 爬楼梯【简单】

题目链接:https://leetcode.cn/problems/climbing-stairs/
参考题解:https://leetcode.cn/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode-solution/

4.1 题目描述

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例1:

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1.1 阶 + 1 阶
2.2 阶

示例2:

输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1.1 阶 + 1 阶 + 1 阶
2.1 阶 + 2 阶
3.2 阶 + 1 阶

提示:

  • 1 <= n <= 45

4.2 解题思路

递归, f(x)=f(x−1)+f(x−2) ,注意好边界条件即可。

4.3 代码实现

class Solution {
public:
    int climbStairs(int n) {
        int fn_2 = 0;
        int fn_1 = 0;
        int fn = 1;
        for(int i = 1; i <= n; ++i) {
            fn_2 = fn_1;
            fn_1 = fn;
            fn = fn_1 + fn_2;
        }
        return fn;
    }
};

5. 排序链表【中等】

题目链接:https://leetcode.cn/problems/sort-list/
参考题解:https://leetcode.cn/problems/sort-list/solution/pai-xu-lian-biao-by-leetcode-solution/

5.1 题目描述

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表

示例1:
在这里插入图片描述

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

示例2:
在这里插入图片描述

输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]

示例3:

输入:head = []
输出:[]

提示:

  • 链表中节点的数目在范围 [0, 5 * 10^4] 内
  • -10^5 <= Node.val <= 10^5

进阶: 你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

5.2 解题思路

对链表进行二分,在二分的过程中要找到链表每一段的起始和结束节点,并且在合并前要先把中间节点给断开。为了实现二分需要找到链表的中间节点,可以用快慢指针实现,快指针每次后移两下,慢指针每次只后移一下,当快指针只指到链表尾时,慢指针所指的就是中间节点了。

5.3 代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(!list1) return list2;
        if(!list2) return list1;
        if(list1->val < list2->val) {
            list1->next = mergeTwoLists(list1->next, list2);
            return list1;
        }
        else {
            list2->next = mergeTwoLists(list1, list2->next);
            return list2;
        }
    }
    ListNode* sortSubList(ListNode* start, ListNode* end) {
        if(start == end)
            return start;
        if(start->next == end) {
            start->next = nullptr;
            return start;
        }
        ListNode* fast = start;
        ListNode* slow = start;
        while(fast->next != end) {
            fast = fast->next;
            slow = slow->next;
            if(fast->next != end)
                fast = fast->next;
        }
        ListNode* mid = slow;
        return mergeTwoLists(sortSubList(start ,mid), sortSubList(mid, end));
    }
    ListNode* sortList(ListNode* head) {
        return sortSubList(head, nullptr);
    }
};

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

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

相关文章

chatgpt赋能Python-python3_9安装numpy

Python 3.9 安装 NumPy 的完整指南 Python是一种功能强大的编程语言&#xff0c;已成为数据分析、人工智能和科学计算领域的主流语言之一。NumPy是一个Python库&#xff0c;用于执行高效的数值计算和科学计算操作。Python 3.9是Python最新版本&#xff0c;带来了许多新功能和改…

一款非常有趣的中国版本的Excalidraw作图工具drawon(桌案)

桌案工具集成了很多有趣的在线作图工具&#xff0c; 思维导图&#xff0c; 流程图&#xff0c;以及草图&#xff0c;在线ppt等功能。 而草图是基于国外有名的Excalidraw而改造而来&#xff0c;使得它更符合国人的使用习惯。 最近在 使用excalidraw时&#xff0c;发现了很多新功…

Excel | 基因名都被Excel篡改了怎么办呢!?~(附3种解决方案)

1写在前面 今天和大家分享一下在做表达矩阵处理时尝尝会遇到的一个问题&#xff0c;但又经常被忽视&#xff0c;就是Excel会修改你的基因名。&#x1f637; 无数大佬在这里都踩过坑&#xff0c;这些普遍的问题已经被写成了paper&#xff08;左右滑动&#xff09;&#xff1a;&a…

75.建立一个主体样式第一部分

我们的目标如下图所示 ● 首先建立文件夹&#xff0c;生成框架代码 ● 把页面上面的HTML元素写进去 <header><nav><div>LOGO</div><div>NAVIGATION</div></nav><div><h1>A healty meal delivered to your door, ever…

Java基础--->并发部分(2)【Java中的锁】

文章目录 synchronized和ReentrantLock的区别Java中锁的名词synchronized锁ReentrantLock锁 synchronized和ReentrantLock的区别 synchronized 和 ReentrantLock 都可以用来实现 Java 中的线程同步。它们的作用类似&#xff0c;但是在用法和特性上还是有一些区别的。 synchroni…

【2023/05/20】Visual Basic

Hello&#xff01;大家好&#xff0c;我是霜淮子&#xff0c;2023倒计时第15天。 Visual Basic是一种广泛应用于Windows操作系统的编程语言&#xff0c;它是Microsoft公司开发的一种面向对象的编程语言&#xff0c;以其简单、易学、易用的特点受到广泛欢迎。本文旨在介绍Visual…

2023年申请美国大学,需要SAT/ACT成绩吗?

受疫情影响&#xff0c;2021 和 2022 年申请美国大学时&#xff0c;许多大学都放宽了SAT/ACT门槛&#xff0c;不强行要求学生提交标化成绩。今年3月&#xff0c;理工大牛院校 MIT 率先打破了这个局面&#xff0c;宣布恢复 SAT/ACT 标化成绩要求&#xff0c;随后几个大学也陆续宣…

Java --- 云尚办公用户管理模块实现

目录 一、用户管理 1.1、数据库表 1.2、使用代码生成器生成相关代码 1.3、后端代码 1.4、前端代码 二、用户与角色功能实现 一、用户管理 1.1、数据库表 CREATE TABLE sys_user (id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 会员id,username VARCHAR(20) NOT NU…

Java面试知识点(全)-spring面试知识点一

Java面试知识点(全) 导航&#xff1a; https://nanxiang.blog.csdn.net/article/details/130640392 注&#xff1a;随时更新 Spring原理 Spring ioc概念&#xff1a;控制权由对象本身转向容器&#xff1b;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系。核心&am…

学术会议参会经验分享一(参会前的准备工作)

前前后后参加了两次学术会议&#xff0c;一次是今年三月份在深圳&#xff0c;另一次是在五月份在南宁&#xff0c;并且两次都进行了主题演讲。总的来说&#xff0c;我感觉参加学术会议重要的是自身能力的提升&#xff0c;比如说演讲、PPT制作等更方面的能力。下面我来分享一些我…

USRP概念基础

GBIC Gigabit Interface Converter的缩写,是将千兆位电信号转换为光信号的接口器件。GBIC设计上可以为热插拔使用。 SFP SFP (Small Form Pluggable)可以简单理解为GBIC(Gigabit Interface Converter的缩写)升级版本,是将千兆位电信号转换为光信号的接口器件,可以热插…

python字符串拼接

首先 什么是字符串拼接 我们来看一个段代码 print("你好""小猫猫")运行结果如下 这是一个最简单的演示 字符串 与 字符串的拼接 两个字符串字面量可以直接用加号 合并成一个字符串 当然 直接这里 字面量字面量 直接写上去看着会非常傻 所以 一般都是 变…

( 动态规划) 516. 最长回文子序列 ——【Leetcode每日一题】

❓516. 最长回文子序列 难度&#xff1a;中等 给你一个字符串 s &#xff0c;找出其中最长的回文子序列&#xff0c;并返回该序列的长度。 子序列定义为&#xff1a;不改变剩余字符顺序的情况下&#xff0c;删除某些字符或者不删除任何字符形成的一个序列。 示例 1&#xf…

MarkDown语法2

MarkDown语法2 一、基本语法 1. 标题 一级标题&#xff1a;# 一级标题二级标题&#xff1a;## 二级标题 2. 字体 斜体&#xff1a;*斜体*,_斜体_粗体&#xff1a;**粗体**&#xff0c;__粗体__粗斜体&#xff1a;***粗斜体***, ___粗斜体___ 3. 线 分割线&#xff1a;&a…

java常用工具之Objects类

目录 简介一、对象判空二、 对象为空时抛异常三、 判断两个对象是否相等四、 获取对象的hashcode五、 比较两个对象六、比较两个数组七、 小结 简介 Java 的 Objects 类是一个实用工具类&#xff0c;包含了一系列静态方法&#xff0c;用于处理对象。它位于 java.util 包中&…

七、Spring Cloud Alibaba-Sentinel

一、引言 1、了解服务可用性问题&#xff0c;服务挂掉原因 缓存击穿、单点故障、流量激增、线程池爆满、CPU飙升、DB超时、缺乏容错机制或保护机制、负载不均、服务雪崩、异常没处理等。 服务雪崩效应&#xff1a;因服务提供者的不可用导致服务调用者的不可用&#xff0c;并将…

Doxygen源码分析: QCString类依赖的qstr系列C函数浅析

2023-05-20 17:02:21 ChrisZZ imzhuofoxmailcom Hompage https://github.com/zchrissirhcz 文章目录 1. doxygen 版本2. QCString 类简介3. qstr 系列函数浅析qmemmove()qsnprintfqstrdup()qstrfree()qstrlen()qstrcpy()qstrncpy()qisempty()qstrcmp()qstrncmp()qisspace()qstr…

C++ VTK网格模型补洞填孔

程序示例精选 C VTK网格模型补洞填孔 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<C VTK网格模型补洞填孔>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。…

如何将Windows图片查看器的背景颜色改成浅色?

现在大家基本都在使用Win10系统&#xff0c;我们在双击查看图片时&#xff0c;系统默认使用系统自带的图片&#xff08;照片&#xff09;查看器去打开图片。图片查看器的背景色默认是黑色的&#xff0c;如下所示&#xff1a;&#xff08;因为大家可能会遇到同样的问题&#xff…

飞浆AI studio人工智能课程学习(3)-在具体场景下优化Prompt

文章目录 在具体场景下优化Prompt营销场景办公效率场景日常生活场景海报背景图生成办公效率场景预设Prompt 生活场景中日常学习Prompt: 给写完的代码做文档 将优质Prompt模板化Prompt 1:Prompt 1:Prompt 2步骤文本过长而导致遗失信息的示例修改后 特殊示例 如何提升安全性主要目…