力扣大厂热门面试算法题 30-32

news2024/12/29 9:46:44

        30. 串联所有单词的子串,31. 下一个排列 ,32. 最长有效括号,每题做详细思路梳理,配套Python&Java双语代码, 2024.03.15 可通过leetcode所有测试用例。

目录

30. 串联所有单词的子串

解题思路

完整代码

Java

Python

31. 下一个排列

解题思路

完整代码

Java

Python

32. 最长有效括号

解题思路

完整代码

Java

Python


30. 串联所有单词的子串

给定一个字符串 s 和一个字符串数组 words words 中所有字符串 长度相同

 s 中的 串联子串 是指一个包含  words 中所有字符串以任意顺序排列连接起来的子串。

  • 例如,如果 words = ["ab","cd","ef"], 那么 "abcdef", "abefcd""cdabef", "cdefab""efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。

返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。

示例 1:

输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:[0,9]
解释:因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。
子串 "barfoo" 开始位置是 0。它是 words 中以 ["bar","foo"] 顺序排列的连接。
子串 "foobar" 开始位置是 9。它是 words 中以 ["foo","bar"] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。

示例 2:

输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
输出:[]
解释:因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。
s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。
所以我们返回一个空数组。

示例 3:

输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
输出:[6,9,12]
解释:因为 words.length == 3 并且 words[i].length == 3,所以串联子串的长度必须为 9。
子串 "foobarthe" 开始位置是 6。它是 words 中以 ["foo","bar","the"] 顺序排列的连接。
子串 "barthefoo" 开始位置是 9。它是 words 中以 ["bar","the","foo"] 顺序排列的连接。
子串 "thefoobar" 开始位置是 12。它是 words 中以 ["the","foo","bar"] 顺序排列的连接。

解题思路

  1. 理解问题:给定一个主字符串 s 和一个字符串数组 wordswords 中所有字符串长度相同。需要找到 s 中所有包含 words 中所有字符串以任意顺序连接形成的子串的起始索引。

  2. 初始化:由于 words 中的所有字符串长度相同,我们可以计算出每个串联子串的总长度,即 wordLength * words.size()。接下来,我们可以在主字符串 s 中遍历长度为此值的所有子串。

  3. 滑动窗口:使用滑动窗口的方法来检查 s 中的每个可能的子串。窗口大小为串联子串的总长度。

  4. 哈希表:使用两个哈希表,一个用来存储 words 数组中单词的出现次数,另一个用来存储当前窗口中与 words 中单词相匹配的单词出现次数。

  5. 遍历:从 s 的第0个字符开始,遍历到 s.length() - windowSize 为止。对于每个可能的子串,使用哈希表来检查是否包含了 words 中所有单词的正确数量。如果是,则将当前子串的起始索引添加到结果列表中。

  6. 返回结果:遍历完成后,返回所有找到的起始索引。

完整代码

Java
public class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> result = new ArrayList<>();
        if (s == null || s.length() == 0 || words == null || words.length == 0) {
            return result;
        }
        
        int wordLen = words[0].length();
        int windowLen = wordLen * words.length;
        Map<String, Integer> wordMap = new HashMap<>();
        for (String word : words) {
            wordMap.put(word, wordMap.getOrDefault(word, 0) + 1);
        }
        
        for (int i = 0; i <= s.length() - windowLen; i++) {
            Map<String, Integer> seenWords = new HashMap<>();
            int j = 0;
            while (j < words.length) {
                String word = s.substring(i + j * wordLen, i + (j + 1) * wordLen);
                if (wordMap.containsKey(word)) {
                    seenWords.put(word, seenWords.getOrDefault(word, 0) + 1);
                    if (seenWords.get(word) > wordMap.get(word)) {
                        break;
                    }
                } else {
                    break;
                }
                j++;
            }
            if (j == words.length) {
                result.add(i);
            }
        }
        
        return result;
    }
}
Python
class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        if not s or not words:
            return []
        
        word_length = len(words[0])
        word_count = len(words)
        window_length = word_length * word_count
        word_map = {}
        for word in words:
            if word in word_map:
                word_map[word] += 1
            else:
                word_map[word] = 1
        
        results = []
        for i in range(len(s) - window_length + 1):
            seen_words = {}
            for j in range(0, window_length, word_length):
                word = s[i + j:i + j + word_length]
                if word in word_map:
                    if word in seen_words:
                        seen_words[word] += 1
                    else:
                        seen_words[word] = 1
                    
                    if seen_words[word] > word_map[word]:
                        break
                else:
                    break
            else:
                results.append(i)
        return results

31. 下一个排列

整数数组的一个 排列  就是将其所有成员以序列或线性顺序排列。

  • 例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3][1,3,2][3,1,2][2,3,1] 。

整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。

  • 例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
  • 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
  • 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。

给你一个整数数组 nums ,找出 nums 的下一个排列。

必须 原地 修改,只允许使用额外常数空间。

示例 1:

输入:nums = [1,2,3]
输出:[1,3,2]

示例 2:

输入:nums = [3,2,1]
输出:[1,2,3]

示例 3:

输入:nums = [1,1,5]
输出:[1,5,1]

解题思路

  1. 从右向左查找:首先从数组的末尾开始向前查找,找到第一个不满足递增关系的元素,记为 nums[i]。这意味着从 nums[i+1]nums[n-1](其中 n 是数组的长度)这部分是按降序排列的。

  2. 查找交换位置:如果找到了这样的 nums[i],再次从数组的末尾开始向前查找,找到第一个大于 nums[i] 的元素,记为 nums[j]

  3. 交换元素:交换 nums[i]nums[j]

  4. 反转子数组:最后,将从 i+1 到数组末尾的部分反转,因为原来这部分是降序的,反转之后变为升序,这样就可以得到下一个排列。

        如果整个数组都是降序排列的,那么它已经是最大的排列,按照题目要求,应该重排为最小排列,即其元素按升序排列。这可以通过直接反转整个数组来实现。

完整代码

Java
public class Solution {
    public void nextPermutation(int[] nums) {
        int i = nums.length - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        if (i >= 0) {
            int j = nums.length - 1;
            while (nums[j] <= nums[i]) {
                j--;
            }
            swap(nums, i, j);
        }
        reverse(nums, i + 1);
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    private void reverse(int[] nums, int start) {
        int i = start, j = nums.length - 1;
        while (i < j) {
            swap(nums, i, j);
            i++;
            j--;
        }
    }
}
Python
class Solution:
    def nextPermutation(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # Step 1: 从右向左找到第一个不是递增的数字
        i = len(nums) - 2
        while i >= 0 and nums[i] >= nums[i + 1]:
            i -= 1
        
        # Step 2: 如果找到了这样的数字,再找一个比它大的最小数字进行交换
        if i >= 0:
            j = len(nums) - 1
            while nums[j] <= nums[i]:
                j -= 1
            # 交换这两个数字
            nums[i], nums[j] = nums[j], nums[i]
        
        # Step 3: 将 i 之后的数字反转,确保是下一个最小的排列
        left, right = i + 1, len(nums) - 1
        while left < right:
            nums[left], nums[right] = nums[right], nums[left]
            left, right = left + 1, right - 1

32. 最长有效括号

给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号

子串

的长度。

示例 1:

输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"

示例 2:

输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"

示例 3:

输入:s = ""
输出:0

解题思路

我们可以使用栈。栈可以帮助我们跟踪未匹配的括号,并且可以用来找出有效子串的长度。具体的做法如下:

  1. 初始化:创建一个栈,并将 -1 推入栈中。这一步是为了在一开始时,栈底有一个元素,便于后面计算长度。

  2. 遍历字符串:遍历给定字符串的每个字符。

    • 如果当前字符是 '(',将其索引推入栈中。
    • 如果当前字符是 ')',首先弹出栈顶元素。
      • 如果此时栈变为空,将当前索引推入栈中。这是因为这个右括号可能是下一个有效子串的起始点的前一个位置。
      • 如果栈不为空,则计算当前有效子串的长度,方法是当前索引减去栈顶元素。更新最长有效括号子串的长度。
  3. 返回结果:在遍历完整个字符串后,最长有效括号子串的长度就被找到了。

完整代码

Java

public class Solution {
    public int longestValidParentheses(String s) {
        int maxLength = 0;
        Stack<Integer> stack = new Stack<>();
        stack.push(-1);  // 初始时压入-1,便于后续计算长度

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(') {
                stack.push(i);  // 将左括号的索引压入栈中
            } else {
                stack.pop();  // 遇到右括号,弹出栈顶元素
                if (stack.isEmpty()) {
                    stack.push(i);  // 如果栈为空,压入当前索引作为新的基准
                } else {
                    maxLength = Math.max(maxLength, i - stack.peek());  // 计算当前有效子串长度
                }
            }
        }

        return maxLength;
    }
}
Python
class Solution:
    def longestValidParentheses(self, s: str) -> int:
        max_length = 0
        stack = [-1]

        for i, char in enumerate(s):
            if char == '(':
                stack.append(i)
            else:
                stack.pop()
                if not stack:
                    stack.append(i)
                else:
                    max_length = max(max_length, i - stack[-1])

        return max_length

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

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

相关文章

UE5.1 iClone8 正确导入角色骨骼与动作

使用iClone8插件Auto Setup 附录下载链接 里面有两个文件夹,使用Auto Setup C:\Program Files\Reallusion\Shared Plugins 在UE内新建Plugins,把插件复制进去 在工具栏出现这三个人物的图标就安装成功了 iClone选择角色,导入动作 选择导出FBX UE内直接导入 会出现是否启动插件…

SpringBoot集成Redisson实现接口限流

系列文章目录 文章目录 系列文章目录前言前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Dat…

由浅到深认识C语言(8)

该文章Github地址&#xff1a;https://github.com/AntonyCheng/c-notes 在此介绍一下作者开源的SpringBoot项目初始化模板&#xff08;Github仓库地址&#xff1a;https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址&#xff1a;https://blog.csdn…

AHU 汇编 实验六

一、实验名称&#xff1a;实验6 输入一个16进制数&#xff0c;把它转换为10进制数输出 实验目的&#xff1a; 培养汇编中设计子程序的能力 实验过程&#xff1a; 源代码&#xff1a; data segmentbuff1 db Please input a number(H):$buff2 db 30,?,30 dup(?),13,10buff3 …

PytorchAPI的使用及在GPU的使用和优化

API 调用API&#xff1a;和手动实现的思路是一样的。#1&#xff0c;#2这两个步骤是通用的步骤&#xff0c;相当于建立一个模型&#xff0c;之后你具体的数据直接丢进去就行了。只需要按着这样的样式打代码就行&#xff0c;死的东西&#xff0c;不需要你自己创造。 import torc…

力扣串题:反转字符串

特殊思路&#xff1a;k的重新赋值&#xff1a;当再加就超过字符串的长度时&#xff0c;需要把k变为字符串的剩余长度&#xff0c;不必理会当剩余长度介于k和2k之间的部分 char* reverseStr(char* s, int k) {for(int i0;i<strlen(s);ii2*k){kik>strlen(s)? strlen(s)-i…

三维卡通数字人解决方案,支持unity和Maya

企业对于品牌形象和宣传手段的创新需求日益迫切&#xff0c;美摄科技凭借其在三维卡通数字人领域的深厚积累&#xff0c;推出了面向企业的三维卡通数字人解决方案&#xff0c;帮助企业轻松打造独具特色的虚拟形象&#xff0c;提升品牌影响力和市场竞争力。 美摄科技的三维卡通…

服务器遭遇挖矿病毒syst3md及其伪装者rcu-sched:原因、症状与解决方案

01 什么是挖矿病毒 挖矿病毒通常是恶意软件的一种&#xff0c;它会在受感染的系统上无授权地挖掘加密货币。关于"syst3md"&#xff0c;是一种特定的挖矿病毒&#xff0c;它通过在受感染的Linux系统中执行一系列复杂操作来达到其目的。这些操作包括使用curl从网络下载…

汇总全网免费API,持续更新(新闻api、每日一言api、音乐。。。)

Public&FreeAPI 网址&#xff1a;apis.whyta.cn &#xff08;推荐&#xff09; UomgAPI 网址&#xff1a;https://api.uomg.com 教书先生 网址&#xff1a;https://api.oioweb.cn/ 山海API https://api.shserve.cn/ 云析API铺 https://api.a20safe.com/ 韩小韩…

AI智能分析网关V4将HTTP消息推送至安防监控视频汇聚EasyCVR平台的操作步骤

TSINGSEE青犀视频智能分析网关V4内置了近40种AI算法模型&#xff0c;支持对接入的视频图像进行人、车、物、行为等实时检测分析&#xff0c;上报识别结果&#xff0c;并能进行语音告警播放。硬件管理平台支持RTSP、GB28181协议、以及厂家私有协议接入&#xff0c;可兼容市面上常…

AI_寻路系统_基本寻路

学习笔记&#xff0c;仅供参考&#xff01; 1、创建了一个新的第三人称项目&#xff0c;重命名为navsystem1. 2、将使用 寻路网格体边界体积&#xff08;Navigation Mesh Bounds Volume&#xff09; 来指定关卡中需要生成寻路的区域。代理将使用此信息在关卡中到达目的地。搜索…

浏览器同源策略及跨域问题

同源策略&#xff1a;同源策略是一个重要的安全策略&#xff0c;它用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档&#xff0c;减少可能被攻击的媒介。 同源策略的作用&#xff1a;保护浏览器中网站的安全&#xff0c;限制ajax只…

汽修门店管理系统,打造高效汽修服务【汽修店软件管理系统】

在汽车后市场&#xff0c;汽修门店的运营效率直接影响着客户的满意度和店铺的利润。为了提升服务质量和工作效率&#xff0c;越来越多的汽修店开始引入汽修门店管理系统。那么&#xff0c;如何搭建汽修店软件管理系统&#xff0c;汽修门店管理系统怎么使用。 首先&#xff0c;我…

python基础——元组【特点,创建,常见操作方法:index,len,count】

&#x1f4dd;前言&#xff1a; 上一篇文章python基础——列表讲解了关于列表的先关知识&#xff0c;还介绍了很多列表的常见操作方法&#xff0c;这篇文章我们就基于上篇文章带大家认识的有关序列的知识&#xff0c;继续讲解python中另一种常见的数据容器——元组&#xff1a;…

(学习日记)2024.03.12:UCOSIII第十四节:时基列表

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

分布式与集群,二者区别是什么?

&#x1f413;分布式 分布式系统是由多个独立的计算机节点组成的系统&#xff0c;这些节点通过网络协作完成任务。每个节点都有自己的独立计算能力和存储能力&#xff0c;可以独立运行。分布式系统的目标是提高系统的可靠性、可扩展性和性能。 分布式服务包含的技术和理论 负…

Linux学习笔记:什么是文件描述符

什么是文件描述符 C语言的文件接口文件的系统调用什么是文件描述符,文件描述符为什么是int类型?为什么新打开的文件的文件描述符不是从0开始? 文件描述符 fd (file descriptor) C语言的文件接口 当时学习C语言的时候,学习了文件接口 具体可以查看之前的文章: 链接:C语言的文…

Elasticsearch:从 Java High Level Rest Client 切换到新的 Java API Client

作者&#xff1a;David Pilato 我经常在讨论中看到与 Java API 客户端使用相关的问题。 为此&#xff0c;我在 2019 年启动了一个 GitHub 存储库&#xff0c;以提供一些实际有效的代码示例并回答社区提出的问题。 从那时起&#xff0c;高级 Rest 客户端 (High Level Rest Clie…

DP-不同的二叉搜索树

给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;5示例 2&#xff1a; 输入&#xff1a;n 1 输出&#xff1a;1提…

Unity URP 如何写基础的曲面细分着色器

左边是默认Cube在网格模式下经过曲面细分的结果&#xff0c;右边是原状态。 曲面细分着色器在顶点着色器、几何着色器之后&#xff0c;像素着色器之前。 它的作用时根据配置信息生成额外的顶点以切割原本的面片。 关于这部分有一个详细的英文教程&#xff0c;感兴趣可以看一…