Leetcode刷题2

文章目录

  • 前言
  • 寻找两个正序数组的中位数
    • 1️⃣ 双指针快速排序
    • 2️⃣ 第k小数解法
  • Z 字形变换
    • 1️⃣ 个人解法
    • 2️⃣巧妙解法1
    • 3️⃣巧妙解法2
  • 字符串转换整数 (atoi)
    • 1️⃣ 常规方法
    • 2️⃣ 作弊方法😫
  • 整数转罗马数字
    • 1️⃣ 常规方法:按照给定规则写出判断条件即可
    • 2️⃣ 循环实现
  • 罗马数字转整数
    • 1️⃣ 常规处理
    • 2️⃣ 改进
  • 总结


前言

    算法小白初入leetcode。本文主要记录个人在leetcode上使用python解题的思路和过程,如果有更好、更巧妙的解题方法,欢迎大家在评论区给出代码或思路。🚀
在这里插入图片描述


寻找两个正序数组的中位数

  • 题目描述

在这里插入图片描述

  • 实际上就是对数组排序的问题

1️⃣ 双指针快速排序

  • 定义两个指针 i i i j j j,初始时分别指向两个列表的开头。然后,比较指针所指的元素,将较小的元素添加到结果列表中,并将对应指针向后移动一位。重复这个过程,直到其中一个列表的所有元素都被添加到结果列表中。最后,将另一个列表中剩余的元素添加到结果列表的末尾。具体代码和执行过程可以如下所示:
class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        num_12 = []
        i   = 0
        j   = 0

        while i<len(nums1) and j <len(nums2):
            if    nums1[i] < nums2[j]:
                num_12.append(nums1[i]) 
                i += 1
            elif  nums1[i] > nums2[j]:
                num_12.append(nums2[j])
                j += 1
            else:   # 如果两个指针指向的数值相同,重复添加该元素,同时移动两个指针
                num_12 += [nums1[i],nums2[j]]
                i += 1
                j += 1
        
        # 若其中一个数组遍历完成了,则将另外一个数组中的剩余元素添加到num_12中 
        while i<len(nums1):
            num_12.append(nums1[i])
            i += 1
        
        while j<len(nums2):
            num_12.append(nums2[j])
            j += 1
        if len(num_12)%2 == 0:
            return (num_12[len(num_12)//2] + num_12[len(num_12)//2 - 1]) / 2
        else :
            return num_12[len(num_12)//2]

在这里插入图片描述在这里插入图片描述

2️⃣ 第k小数解法

  • 这个解法是众多题解中非常巧妙的一个,具体原理和算法可以直接看这里:第k小数解法视频详解
  • 算法实现:知道原理后,其实本质就是在不断排除比中位数还要小的那些数,直到找到中位数,所以可以利用递归的方式去实现它。
class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        total_length = len(nums1) + len(nums2)
        
        if total_length % 2 == 1:
            # 如果总长度为奇数,则中位数为第 (total_length // 2 + 1) 小的元素
            return self.findKthElement(nums1, nums2, total_length // 2 + 1)
        else:
            # 如果总长度为偶数,则中位数为第 total_length // 2 和第 total_length // 2 + 1 小的元素的平均值
            left = self.findKthElement(nums1, nums2, total_length // 2)
            right = self.findKthElement(nums1, nums2, total_length // 2 + 1)
            return (left + right) / 2
            
    def findKthElement(self,nums1, nums2, k):
        """
        nums1: 第一个有序数组
        nums2: 第二个有序数组
        k    : 要查找的第 k 小的元素(1-indexed)
        返回值: 第 k 小的元素
        """
        len1, len2 = len(nums1), len(nums2)
        
        # 确保 nums1 是较短的数组
        if len1 > len2:
            return self.findKthElement(nums2, nums1, k)
        
        # 如果较短数组为空,则直接返回 nums2 中的第 k 个元素
        if len1 == 0:
            return nums2[k-1]
        
        # 如果 k == 1,则返回两个数组中第一个元素的最小值
        if k == 1:
            return min(nums1[0], nums2[0])
        
        # 选择 nums1 和 nums2 中的 k//2 个元素,比较这两个元素
        i = min(len1, k // 2)
        j = min(len2, k // 2)
        
        if nums1[i-1] > nums2[j-1]:
            # 如果 nums1 中第 i 个元素较大,则说明 nums2 中的前 j 个元素不可能是第 k 小的元素
            return self.findKthElement(nums1, nums2[j:], k - j)
        else:
            # 如果 nums2 中第 j 个元素较大,则说明 nums1 中的前 i 个元素不可能是第 k 小的元素
            return self.findKthElement(nums1[i:], nums2, k - i)

在这里插入图片描述确实是又快了一些,可惜才击败三十多,想知道更快的解法💡

Z 字形变换

  • 题目描述

在这里插入图片描述

1️⃣ 个人解法

  • 可以发现每一行的字符都与第一行的字符存在关联的,所以只要先确定第一行的元素,后面几行的元素就能确定了。如题目描述中的示例2,第二行字符ALSIG可以认为是第一行字符PIN中每个元素在 s s s中的索引位置向左和右各移动 1 1 1次得到(超出索引位置就舍弃掉),第二行字符YAHR可以认为是第一行字符PIN中每个元素在 s s s中的索引位置向左和右各移动 2 2 2次得到(超出索引位置就舍弃掉),依次类推…
    但是要注意两点:1):最后一行的字符按照这样的处理会导致出现重复,所以需要单独处理;2):如果是下面这种情况,按照这样的处理就会导致末尾RI这两个字符遗漏,所以由第一行字符中最后一个字符确定其他行字符时,需要单独处理。

在这里插入图片描述

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        '''
        思路:先确定第一行和最后一行的元素,后面几行的元素顺序与第一行有关
        '''
        if numRows == 1:
            return s
        line1       = ''
        line1_index = []
        length      = len(s)
        for i in range(0,length,2*(numRows-1)):
            line1 += s[i]
            line1_index.append(i)

        for i in range(numRows-1):
            next_line = ''
            index = []
            for j in line1_index:
                if i == numRows-2:    #最后一行作特殊处理
                    if j+numRows-1 < length:
                        next_line += s[j+numRows-1]
                else:
                    if j-i-1 > 0:
                        next_line += s[j-i-1]
                    if j+i+1 < length:
                        next_line += s[j+i+1]
                    if j == line1_index[-1] and j+2*numRows-3-i < length:
                        next_line += s[j+2*numRows-3-i]
            line1 += next_line
        return line1
            

在这里插入图片描述
不过时间效率并不高,有待优化🤦‍♂️

2️⃣巧妙解法1

  • 参考leetcode-wuji3

在这里插入图片描述


class Solution:
    def convert(self, s: str, numRows: int) -> str:
        temp = [i for i in range(numRows)]
        temp += temp[1:-1][::-1]

        res = [''] * numRows
        n = len(s)

        for i in range(n):
            res[temp[i%len(temp)]] += s[i]

        return ''.join(res)

在这里插入图片描述
思路清晰,代码简洁,确实很巧妙!

3️⃣巧妙解法2

  • 使用变量 i i i 表示当前字符的行索引,初始值为 0 0 0;使用变量 f l a g flag flag 表示行索引的变化方向,初始值为 − 1 -1 1。然后遍历原字符串中的每个字符 c c c:将当前字符 c c c 添加到 r e s [ i ] res[i] res[i] 对应的行中。如果当前行索引 i 到达首行或末行,则改变 f l a g flag flag 的方向。最后根据 f l a g flag flag 的方向更新行索引 i i i,这样一来就实现了“Z”字形的逻辑。
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if numRows < 2:
            return s
        res = ['' for i in range(numRows)]
        i , flag = 0,-1
        for c in s:
            res[i] += c
            if i == 0 or i == numRows - 1:
                flag = -flag
            i = i + flag
        return ''.join(res)

在这里插入图片描述

字符串转换整数 (atoi)

  • 题目描述:

在这里插入图片描述

1️⃣ 常规方法

  • 按照题目,思路如下:
    • 第一步去掉字符串前面的所有空格;
    • 分类讨论,只保留符合条件的字符:
      • 首字符是-或者+的情况:从第二个字符遍历到最后一个字符,满足条件的字符留下。对于是否保留 0 0 0这个字符,可以通过最终拼接的字符串re的长度来判断,如果等于 0 0 0说明是前置零,直接舍弃,其余情况则保留。对于非数字字符的判断,可以通过 A s c a l l Ascall Ascall码来进行判断。
      • 其他情况:同上处理,只不过从开头遍历到结尾。
    • 将最后拼接的字符串转换成整数并输出。
class Solution:
    def myAtoi(self, s: str) -> int:

        s = s.strip()
        re  = ''

        if s == '':
            return 0
        elif s[0] == '-' or s[0] == '+':
            i = 1
            while i <= len(s)-1:
                if ord(s[i]) < 48 or ord(s[i]) > 57:
                    break
                if len(re) == 0  and s[i] == 0:
                    continue
                else:
                    re += s[i]
                i += 1
            if len(re) == 0:
                return 0
            elif s[0] == '-':
                return max(-int(re),-2**31)
            else:
                return min(int(re),2**31-1)
        else:
            i = 0
            while i <= len(s)-1:
                if ord(s[i]) < 48 or ord(s[i]) > 57:
                    break
                if len(re) == 0  and s[i] == 0:
                    continue
                else:
                    re += s[i]
                i += 1
            
            if len(re) == 0:
                return 0
            else:
                return min(int(re) , 2**31-1)

在这里插入图片描述

2️⃣ 作弊方法😫

  • 其实Python中的内置函数int可以直接实现这个题目的大部分情况,我们直接拿来使用,然后对于使用不了的情况就用try ... except进行捕捉,然后再使用上面的常规方法。
class Solution:
    def myAtoi(self, s: str) -> int:
        try:
            return max(int(s),-2**31) if '-' in s else min(int(s),2**31-1) 
        except Exception as e:
            s = s.strip()
            re  = ''

            if s == '':
                return 0
            elif s[0] == '-' or s[0] == '+':
                i = 1
                while i <= len(s)-1:
                    if ord(s[i]) < 48 or ord(s[i]) > 57:
                        break
                    if len(re) == 0  and s[i] == 0:
                        continue
                    else:
                        re += s[i]
                    i += 1
                if len(re) == 0:
                    return 0
                elif s[0] == '-':
                    return max(-int(re),-2**31)
                else:
                    return min(int(re),2**31-1)
            else:
                i = 0
                while i <= len(s)-1:
                    if ord(s[i]) < 48 or ord(s[i]) > 57:
                        break
                    if len(re) == 0  and s[i] == 0:
                        continue
                    else:
                        re += s[i]
                    i += 1
                
                if len(re) == 0:
                    return 0
                else:
                    return min(int(re) , 2**31-1)            

在这里插入图片描述确实提速了一些hhh

整数转罗马数字

  • 题目描述

在这里插入图片描述

1️⃣ 常规方法:按照给定规则写出判断条件即可

class Solution:
    def intToRoman(self, num: int) -> str:
        char_num = {1:'I',5:'V',10:'X',50:'L',100:'C',500:'D',1000:'M',4:'IV',9:'IX',40:'XL',90:'XC',400:'CD',900:'CM'}
        re = ''
        while num > 0:
            if 1000 <= num:
                re += char_num[1000]
                num -= 1000
            elif 900 <= num < 1000:
                re += char_num[900]
                num -= 900
            elif 500 <= num < 900:
                re += char_num[500]
                num -= 500  
            elif 400 <= num < 500:
                re += char_num[400] 
                num -= 400
            elif 100 <= num < 400:
                re += char_num[100]
                num -= 100
            elif 90 <= num < 100:
                re += char_num[90]
                num -= 90
            elif 50 <= num < 90:
                re += char_num[50]
                num -= 50
            elif 40 <= num < 50:
                re += char_num[40]
                num -= 40
            elif 10 <= num < 40:
                re += char_num[10]
                num -= 10
            elif 9 <= num < 10:
                re += char_num[9]
                num -= 9
            elif 5 <= num < 9:
                re += char_num[5]
                num -= 5
            elif 4 <= num < 5:
                re += char_num[4]
                num -= 4
            elif 1 <= num < 4:
                re += char_num[1]
                num -= 1

        return re

在这里插入图片描述

2️⃣ 循环实现

  • 将上面判断改成循环的方式实现
class Solution:
    def intToRoman(self, num: int) -> str:
        char_num = {1000:'M', 900:'CM', 500:'D', 400:'CD', 100:'C', 90:'XC', 50:'L', 40:'XL', 10:'X', 9:'IX', 5:'V', 4:'IV', 1:'I'}
        re = ''
        for i in char_num.keys():
            if num // i != 0:
                re += char_num[i] * (num//i)
                num = num % i 
        return re

在这里插入图片描述
不过速度变慢了一些

罗马数字转整数

  • 题目描述(上面一题的相反处理)

在这里插入图片描述

1️⃣ 常规处理

  • 先将字符串中特殊的 6 6 6种罗马数字挑选出来转换成整数,然后再将剩下的罗马单个字符一一转换成数字即可。
class Solution:
    def romanToInt(self, s: str) -> int:
        dict1 = {'I': 1,'V': 5,'X': 10,'L': 50,'C': 100,'D': 500,'M': 1000}
        dict2 = {'IV': 4,'IX': 9,'XL': 40,'XC': 90,'CD': 400,'CM': 900}
        result = 0
        for i in dict2.keys():
            if i in s:
                result += dict2[i]
                s       = s.replace(i,'')
        for i in s:
            result += dict1[i]
        return result

在这里插入图片描述

2️⃣ 改进

  • 上面算法需要遍历两次字符串,时间复杂度为 O ( 2 n ) \mathcal{O(2n)} O(2n),其实只需要遍历一次就行,时间复杂度变成 O ( n ) \mathcal{O(n)} O(n)
class Solution:
    def romanToInt(self, s: str) -> int:
        dict1 = {'I': 1,'V': 5,'X': 10,'L': 50,'C': 100,'D': 500,'M': 1000}
        dict2 = {'IV': 4,'IX': 9,'XL': 40,'XC': 90,'CD': 400,'CM': 900}
        result = 0

        while len(s) >= 1:
            if len(s) == 1:
                result += dict1[s[0]]
                s = ''
            elif dict1[s[0]] < dict1[s[1]]:
                result += dict2[s[0:2]]
                s = s[2:]
            else:
                result += dict1[s[0]]
                s = s[1:]
        return result   

在这里插入图片描述

总结

算法小白初入leetcode,期待给出更精妙的算法🚀🚀🚀

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

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

相关文章

ABB机器人手动模式切换自动模式时,速度自动更改为100%的解决办法

ABB机器人手动模式切换自动模式时,速度自动更改为100%的解决办法 如下图所示,手动切换到自动模式时,示教器上提示:速度将改为100%,但是我们正常使用时的速度可能不是100%,所以还需要手动去更改速度,不太方便。。。 解决办法可参考以下内容: 如下图所示,打开菜单—控制…

防火墙技术基础篇:解析防火墙的网络隔离机制

防火墙技术基础篇&#xff1a;解析防火墙的网络隔离机制 网络安全在现代社会中扮演着重要的角色&#xff0c;保护网络系统、用户和数据免受未经授权的访问、破坏和窃取。个人、企业和国家都需要加强网络安全意识&#xff0c;采取有效措施保护自身的网络安全。随着网络攻击手段…

Golang实现递归复制文件夹

代码 package zdpgo_fileimport ("errors""os""path/filepath""strings" )// CopyDir 复制文件夹 // param srcPath 源文件夹 // param desPath 目标文件夹 // return error 错误信息 func CopyDir(srcPath, desPath string) error {…

张量 t-product 积(matlab代码)

参考文献&#xff1a;Tensor Robust Principal Component Analysis with a New Tensor Nuclear Norm 首先是文章2.3节中 t-product 的定义&#xff1a; 块循环矩阵&#xff1a; 参考知乎博主的例子及代码&#xff1a;&#xff08;t-product与t-QR分解&#xff0c;另一篇傅里叶对…

200smart【编程入门】

说明 编程时&#xff0c;遇到困难就按【F1】 【I】输入 200smart 上限 i0.0~i31.7 255bit【255个输入点】 i0.0~i31.7 八进制 【布尔 bool 】 ib0~ib127 【单字节】 8bit iw0~iw127 …

六零导航页 file.php 任意文件上传漏洞复现(CVE-2024-34982)

0x01 产品简介 LyLme Spage(六零导航页)是中国六零(LyLme)开源的一个导航页面。致力于简洁高效无广告的上网导航和搜索入口,支持后台添加链接、自定义搜索引擎,沉淀最具价值链接,全站无商业推广,简约而不简单。 0x02 漏洞概述 六零导航页 file.php接口处任意文件上传…

Java面试八股之++操作符是线程安全的吗

操作符是线程安全的吗 操作符本身在Java中并不是线程安全的。这个操作实际上包含三个步骤&#xff1a;读取变量的值、将值加1、然后将新值写回内存。在多线程环境下&#xff0c;如果多个线程同时对同一个变量执行操作&#xff0c;就可能出现竞态条件&#xff08;race conditio…

TransFormer学习之基础知识:STN、SENet、CBAM、Self-Attention

1.空间注意力机制STN 参考链接&#xff1a;STN(Spatial Transformer Networks) 参考链接&#xff1a;通俗易懂的Spatial Transformer Networks(STN) 核心动机&#xff1a; 在空间中捕获重要区域特征(如图像中的数字)&#xff0c;将核心区域进行放大居中&#xff0c;使得结果更…

K8S认证|CKA题库+答案| 7. 调度 pod 到指定节点

7、调度 pod 到指定节点 您必须在以下Clusterd/Node上完成此考题&#xff1a; Cluster Master node Worker node hk8s master …

GS5812G 21V、2A同步降压DC/DC转换器芯片IC

一般描述 该GS5812G是一个同步降压DC/DC转换器与快速恒定的时间(FCOT)模式控制。该器件提供4. 5V至21V的输入电压范围和2A连续负载电流能力。它是恒定时间脉宽调制(PWM)控制器&#xff0c;支持 FCOT模式控制。工作频率取决于输入和输出电压条件。 该GS5812G故障…

桌面藏线大法

1有线改无线&#xff1a; 蓝牙鼠标 蓝牙键盘 蓝牙耳机 2将排插贴到桌子底下 购物软件上搜 3断舍离 不要的电子产品统统扔掉 4 洞洞板和挂钩 这个不用介绍了

uniapp中使用mockjs模拟接口测试总结(swiper轮播图示例)

完整总结下在uni-app中如何使用Mock.js模拟接口测试&#xff0c;这在后台接口未就绪的情况下非常有用。同时也给出个首页swiper轮播图的mock接口使用。网上的文章都不太完整&#xff0c;这里总结下完整的使用示例&#xff0c;同时也支持h5和小程序平台&#xff0c;分享给需要的…

个人感觉对Material设计有用的几个网址

(一) Modular and customizable Material Design UI components for Android GIthub: material-components-android (二) 学习Material设计 Material Design (三) 用于创建Material主题&#xff0c;支持导出多种格式 material-theme-builder

谷歌蜘蛛池是什么?

或称为谷歌爬虫池&#xff0c;是一项专门针对谷歌搜索引擎优化&#xff08;SEO&#xff09;的先进技术&#xff0c;这种技术的主要目的是通过建立庞大的网站群体和复杂的链接结构来吸引和维持谷歌的爬虫程序的注意力&#xff0c;其核心是通过这种结构优化&#xff0c;增强特定网…

ESP32 实现获取天气情况

按照小安派AiPi-Eyes天气站思路&#xff0c;在ESP32 S3上实现获取天气情况。 一、在ESP32 S3实现 1、main.c 建立2个TASK void app_main(void) {//lvgl初始化xTaskCreate(guiTask, "guiTask", 1024 * 6, NULL, 5, NULL);//wifi初始化、socket、json处理taskcustom_…

Xcode代码格式化SwiftFormat安装使用,以及不生效问题

官方仓库地址&#xff1a;GitHub - nicklockwood/SwiftFormat: A command-line tool and Xcode Extension for formatting Swift code 安装SwiftFormat 有两种安装方式&#xff0c;两种方式都可以&#xff0c;二选一即可&#xff1a; 第一种使用brew&#xff0c;如果已经使用…

AWPortrait1.4更新,人物的生成更加趋近真实感,将SD1.5人像的真实感提升到了一个新的高度

AWPortrait1.4更新&#xff0c;人物的生成更加趋近真实感&#xff0c;将SD1.5人像的真实感提升到了一个新的高度 经过5个月&#xff0c;AWPortrait终于迎来了1.4。 本次更新基于1.3训练&#xff0c;使得人物的生成更加趋近真实感&#xff0c;将SD1.5人像的真实感提升到了一个新…

《二》MP3在线搜索所歌曲的实现

上一期我们大致实现了布局等操作 那么这一期我们来实现如何去搜索歌曲&#xff1a; 首先呢&#xff0c;我们是设计多媒体&#xff0c;要包含多媒体类头文件&#xff0c;还要能在线搜索&#xff0c;那就要包含网络上的头文件&#xff0c;还要实现打开文件操作&#xff0c;处理…

618知识狂欢,挑本好书,点亮智慧生活!

618精选编程书单&#xff1a;提升你的代码力 一年一度的618又到啦&#xff01;今年的618就不要乱买啦&#xff0c;衣服买多了会被淘汰&#xff0c;电子产品买多了会过时&#xff0c;零食买多了会增肥&#xff0c;最后怎么看都不划算。可是如果你购买知识&#xff0c;坚持阅读&a…

k8s节点亲和性配置

在Kubernetes中&#xff0c;你可以使用节点亲和性&#xff08;Node Affinity&#xff09;来控制Pod调度到特定的节点上。节点亲和性是通过Pod的spec.affinity.nodeAffinity属性来设置的。 以下是一个配置节点亲和性的YAML示例&#xff1a; apiVersion: v1 kind: Pod metadata…