leetcode hot100刷题(1)

news/2025/3/6 23:35:36/文章来源:https://www.cnblogs.com/niedongliang/p/18756790

目录
  • 1. 两数之和
  • 49. 字母异位词分组
    • 他山之石
    • 语法学习
  • 128. 最长连续序列
    • 他山之石
    • 语法学习
  • 283. 移动零
    • 他山之石

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

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

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int, int> hashtable;for (int i = 0; i < nums.size(); ++i) {auto it = hashtable.find(target - nums[i]);if (it != hashtable.end()) {return {it->second, i};}hashtable[nums[i]] = i;}return {};}
};

注意:如果不采用这种一般将数据压入hashtable一边判断而是采用先将所有数据全部压入hashtable后再一个给判断过不了样例2

49. 字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例 1:

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

示例 2:

输入: strs = [""]
输出: [[""]]

示例 3:

输入: strs = ["a"]
输出: [["a"]]

提示:

  • 1 <= strs.length <= 104
  • 0 <= strs[i].length <= 100
  • strs[i] 仅包含小写字母

方法一:排序

时间复杂度:$O(nklogk)$,其中 n 是 strs 中的字符串的数量,k是 strs 中的字符串的的最大长度。

class Solution {
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {unordered_map<string,vector<string>> hashtable;vector<string> tmp(strs);for(int i=0;i<strs.size();i++) sort(tmp[i].begin(),tmp[i].end());for(int i=0;i<strs.size();i++)hashtable[tmp[i]].push_back(strs[i]);vector<vector<string>> res;for(auto it:hashtable) res.push_back(it.second);return res;}
};

注意:下面代码只会对tmp的副本排序,所以tmp[i]仍然没有被排序,需要将for(string s:tmp) sort(s.begin(),s.end());改成for(string& s:tmp) sort(s.begin(),s.end());

class Solution {
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {unordered_map<string,vector<string>> hashtable;vector<string> tmp(strs);for(string s:tmp) sort(s.begin(),s.end());for(int i=0;i<strs.size();i++)hashtable[tmp[i]].push_back(strs[i]);vector<vector<string>> res;for(auto it:hashtable) res.push_back(it.second);return res;}
};

他山之石

由于互为字母异位词的两个字符串包含的字母相同,因此两个字符串中的相同字母出现的次数一定是相同的,故可以将每个字母出现的次数使用字符串表示,作为哈希表的键。

由于字符串只包含小写字母,因此对于每个字符串,可以使用长度为 26 的数组记录每个字母出现的次数。需要注意的是,在使用数组作为哈希表的键时,不同语言的支持程度不同,因此不同语言的实现方式也不同。

class Solution {
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {// 自定义对 array<int, 26> 类型的哈希函数auto arrayHash = [fn = hash<int>{}] (const array<int, 26>& arr) -> size_t {return accumulate(arr.begin(), arr.end(), 0u, [&](size_t acc, int num) {return (acc << 1) ^ fn(num);});};unordered_map<array<int, 26>, vector<string>, decltype(arrayHash)> mp(0, arrayHash);for (string& str: strs) {array<int, 26> counts{};int length = str.length();for (int i = 0; i < length; ++i) {counts[str[i] - 'a'] ++;}mp[counts].emplace_back(str);}vector<vector<string>> ans;for (auto it = mp.begin(); it != mp.end(); ++it) {ans.emplace_back(it->second);}return ans;}
};

原文链接:https://leetcode.cn/problems/group-anagrams/solutions/520469/zi-mu-yi-wei-ci-fen-zu-by-leetcode-solut-gyoc/

语法学习

std::array 是 C++ 标准库提供的静态数组,长度固定,但有更多功能,如边界检查

C++11 之后,vector 容器中添加了新的方法:emplace_back() ,和 push_back() 一样的是都是在容器末尾添加一个新的元素进去,不同的是 emplace_back() 在效率上相比较于 push_back() 有了一定的提升。

#include <vector>
#include <iostream>
using namespace std;
int main() {vector<pair<int, string>> vec;// 使用 push_back 需要显式构造对象vec.push_back(make_pair(1, "Apple"));// 使用 emplace_back 直接构造对象vec.emplace_back(2, "Banana");for (const auto& p : vec) {cout << p.first << " - " << p.second << endl;}return 0;
}

C++中push_back和emplace_back的区别 - 知乎

自定义hash函数

在C++中如何对自定义类型做hash操作_c++自定义哈希函数-CSDN博客

128. 最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2:

输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

示例 3:

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

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
class Solution {
public:int longestConsecutive(vector<int>& nums) {set<int> s(nums.begin(),nums.end());nums.clear();for(int num:s) nums.push_back(num);int res=(nums.size()!=0);int l=0,r=1;int n=nums.size();while(r<n){while(r<n&&nums[r]-nums[r-1]==1){r++;}res=max(res,r-l);l=r;r=r+1;}return res;}
};

他山之石

本题不能排序,因为排序的时间复杂度是 $O(n\log n)$,不符合题目 $O(n)$ 的要求。

核心思路:

对于 nums 中的元素 x,以 x 为起点,不断查找下一个数 x+1, x+2, ... 是否在 nums 中,并统计序列的长度。

关键优化(使时间复杂度达到 $O(n)$):

  1. 使用哈希集合

    • nums 中的数存入哈希集合,这样可以 $O(1)$ 判断数字是否存在。
  2. 避免重复计算

    • 如果 x-1 存在于哈希集合中,则不以 x 为起点
    • 这样可以保证我们只会从连续序列的第一个数开始计算,避免大量重复计算。
    • 例如 nums = [3,2,4,5]
      • 3 开始,我们可以找到 3,4,5 这个连续序列。
      • 2 开始,我们可以找到 2,3,4,5,一定比从 3 开始的更长,因此 3 不是一个合适的起点。

细节优化:

  • 遍历哈希集合,而不是 nums 本身!
    • 例如 nums = [1,1,1,...,1,2,3,4,5,...](前一半都是 1)。
    • 遍历 nums 会导致每个 1 都执行 $O(n)$ 的循环,总复杂度变为 $O(n^2)$,从而超时。
class Solution {
public:int longestConsecutive(vector<int>& nums) {int res=0;unordered_set<int> hashtable(nums.begin(),nums.end());for(int x:hashtable){if(hashtable.contains(x-1)) continue;//x是序列的起点int y=x+1;while(hashtable.contains(y)) y++;//循环结束后,y-1是最后一个在连续数res=max(res,y-x);}return res;}
};

语法学习

从C++11到C++23(六)C++20利用contains查询map是否存在某个键_c++ map contains-CSDN博客

C++20新增了std::map::contains可以直接查找键是否存在,返回值类型为bool型

#include <iostream>
#include <string>
#include <map>int main()
{std::map<int, std::string> example = {{1, "One"}, {2, "Two"}, {3, "Three"}, {42, "Don\'t Panic!!!"}};if(example.contains(42)) {std::cout << "Found\n";} else {std::cout << "Not found\n";}
}

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]

提示:

  • 1 <= nums.length <= 104
  • -231 <= nums[i] <= 231 - 1

进阶:你能尽量减少完成的操作次数吗?

class Solution {
public:void moveZeroes(vector<int>& nums) {int i=0,j=0;int n=nums.size();while(i<n&&j<n){while(n>i&&nums[i]) i++;j=i+1;while(n>j&&!nums[j]) j++;if(n>i,n>j) swap(nums[i],nums[j]);i++;}}
};

他山之石

📌 核心思路

我们将 0 视作 空位,把所有 非零元素 依次移动到数组左侧的空位,同时 保持原有顺序

示例

cpp复制编辑输入: nums = [0, 1, 0, 3, 12]
输出: [1, 3, 12, 0, 0]

💡 关键点

  1. 维护一个指针 i0,指向最左侧的 空位(即 0)。
  2. 遍历数组
    • 遇到非零元素 → 交换 nums[i]nums[i0],然后 i0++
    • 遇到 0 → 不操作,继续遍历。

📜 代码

class Solution {
public:void moveZeroes(vector<int>& nums) {int i0 = 0;  // 记录最左侧空位for (int& x : nums) { // if (x) { // 只有非零元素才交换swap(x, nums[i0]);i0++; // 更新最左侧空位}}}
};

📊 复杂度分析

  • 时间复杂度:O(n),遍历 nums 一次,每个元素最多交换一次。
  • 空间复杂度:O(1),原地修改,没有额外空间消耗。

🧐 运行过程解析

示例

输入: nums = [0, 1, 0, 3, 12]
i i0 nums[i] 交换后 nums
0 0 0 不操作
1 0 1 [1, 0, 0, 3, 12]
2 1 0 不操作
3 1 3 [1, 3, 0, 0, 12]
4 2 12 [1, 3, 12, 0, 0]

最终输出:

[1, 3, 12, 0, 0]

💬 可能的疑问

❓ Q1: 为什么可以i0=0

  • 实际上i0会自动找到第一个为0的元素
  • 例如

    nums = [1, 2, 3, 4,0,12]
    
    1. 发现 1,交换 nums[0]nums[0][1, 2, 3, 4,0,12],i0=1
    2. 发现 2,交换 nums[1]nums[1][1, 2, 3, 4,0,12],i0=2
    3. 发现 3,交换 nums[2]nums[2][1, 2, 3, 4,0,12],i0=3
    4. 发现 4,交换 nums[3]nums[3][1, 2, 3, 4,0,12],i0=4
    5. 发现 0,交换 nums[4]nums[4][1, 2, 3, 4,0,12],i0=4
    6. 发现 12,交换 nums[5]nums[4][1, 2, 3, 4,12,0],i0=5

原文链接

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025.3.6 起步

今天学习了web安全的基本知识 1,http,一种协议,常用TCP 2,http的请求方法(GET/POST/PUT...)和请求状态(200 OK/404 NOT FOUND...) 3,URL网址,及其组成 4,UA头,User-Agent,可以知道操作系统、CPU、浏览器类型 5,BurpSuite抓包返回包,可以得到很多信息6,Referer,告诉…

《AI时代生存手册:零基础掌握DeepSeek》 - PDF免费下载

通过本书,你将轻松上手DeepSeek,开启智能生活新篇章。通过本书,你将学会用Deepseek大幅提升工作效率,告别烦琐,拥抱高效。通过本书,你将学会如何让Deepseek成为您的职场超级助手。通过本书,你将学会如何利用DeepSeek激发自己的创作灵感,打造爆款内容,打造个人品牌。通…

Hive安装--本地模式

系统版本:CentOS Linux release 7.9.2009 (Core)ps: 最小化安装一、安装MySQL 1.下载 1.1安装包 官网:https://downloads.mysql.com/archives/community/1.2驱动 官网:https://downloads.mysql.com/archives/c-j/ps mysql-connector-java-5.1.47.jar,要这个2.安装 2.1安装依…

极空间docker部署Ghost博客

1. 下载镜像搜索不到、下载不了的请挂代理或者换源2. 编辑容器 2.1 将content路径映射到nas本地2.2 映射本地端口到ghost端口 注意:极空间限制了3000以内的端口不可外部访问,所以要设置成>3000的端口,我这里设置的33682.3 配置环境变量 这里我选择sqlite3作为数据库,url…

19C++循环结构-多重循环(2)-——教学

1、三重循环与程序的优化; 2、四重循环; 3、超市收费程序一、三重循环与程序的优化 教学视频 百钱买百鸡 3文钱可以买1只公鸡,2文钱可以买1只母鸡,1文可以买3只小鸡,要用100文买100只(每种鸡必买1只)。 试编一程序,求公鸡,母鸡、小鸡各有多少只? 如果100文钱全部买公…

fastadmin + workman 实现websocket前后端通信http

1.安装workman扩展composer require workerman/workerman2.安装think-workercomposer require topthink/think-worker=1.0.* 3.如果在windows下使用,还需下载composer require workerman/workerman-for-win4.根目录创建server.php 。用来启动服务#!/usr/bin/env php <?php…

日报202536

继续学习了Springboot,感觉有点麻烦:User package com.xxx.demo1.pojo;public class User {String id;String name;@Overridepublic String toString() {return "User{" +"id=" + id + \ +", name=" + name + \ +};}public String getId() {re…

[JLOI2014] 路径龟划

传送门 我的部落格 貌似没有比较通俗介绍红绿灯期望介绍方法的?我来一发不需要积分基础能看懂的严谨证明~ 题目大意 这道题 luogu 题面不太清晰,大意给定一张无向图,你需要开车从起点走到终点,有些点会设红绿灯,给出每个红绿灯的红灯时间和绿灯时间,你见到红绿灯时红绿灯…

Vue 脚手架发展

Vue 脚手架是一个基于 Vue.js 进行快速开发的完整系统,Vue 脚手架致力于将 Vue 生态中的工具基础标准化。Vue 的工具链 CLI(通常指 @vue/cli)与 create-vue 是 Vue 生态中两个不同的脚手架工具,它们在功能定位、技术栈和适用场景上有显著区别。 Vue CLI(@vue/cli) Vue CL…

18C++循环结构-多重循环(1)

1、循环的嵌套; 2、双重循环的应用一、循环的嵌套 问题:#include <iostream> using namespace std; int main() {int j;for(j=1;j<=5;j++)cout<<*;return 0; }再编一程序,每次输出3行,每行5个"*"号。 在外层加一个循环语句来实现;流程图如:#inc…

Mybatis-plus01--快速开始

前言 在编写Java开发过程中,尤其是CRUD开发,我们会发现大部分事件都在编写Java持久层的增删改查上了,并且配置mybatis的mapper文件也是一件麻烦的事。如果你也有这样的烦劳,看来就可以认识一下我们的新朋友mybatis-plus了。 MyBatis-Plus 是一个 Mybatis的增强工具,在 MyB…