242.有效的字母异位词,349. 两个数组的交集,202题. 快乐数,1. 两数之和

简介: 以下是根据您提供的内容编写的一段简介:在算法学习中,掌握高效解法和数据结构至关重要。本文通过解析四道LeetCode经典题目(242.有效的字母异位词、349.两个数组的交集、202.快乐数、1.两数之和),深入探讨了多种优化思路与常用数据结构的应用。例如,使用数组统计字符频率判断异位词,利用`unordered_set`实现集合交集去重,借助`unordered_map`优化两数之和的查找效率,以及通过哈希表检测快乐数循环问题。这些方法不仅提升了时间复杂度,还强化了对`map`、`set`等数据结构的理解,为解决类似问题提供了重要参考。

题目:242.有效的字母异位词

Leetcode原题:242. 有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

示例 1:

输入: s = "anagram", t = "nagaram"

输出: true

示例 2:

输入: s = "rat", t = "car"

输出: false

提示:

1 <= s.length, t.length <= 5 * 104

s 和 t 仅包含小写字母

思考历程与知识点:  

如果一个字母一个字母的找,也就是暴力,用两个for的话时间复杂度是O(N^2);

我们可以换个思路,a~z一共26个字母,我们开一个长度26的数组 f,把每个字母出现的次数记录下来, a 就是 f [0], b 就是 f [1],c就是 f [2] , 依此类推,第二个字符串也是同样开一个26的数组 f2 [ ]。最后只需要对比两个数组里的次数是否都相同就可以了。

题解:

class Solution {
public:
    bool isAnagram(string s, string t) {
        int f[26]={0},f2[26]={0};
 
        if(s.size()!=t.size())return false;// 长度不一样的话,肯定不对
       
        for(int i = 0; i < s.size(); i++) {
            f[s[i] - 'a']++;
            f2[t[i] - 'a']++;
        }
 
        for(int i = 0; i < 26; i++) {
            if(f[i] != f2[i]) return false;
        }
 
        return true;
 
    }
};

题目:349. 两个数组的交集

Leetcode原题:349. 两个数组的交集

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]

输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]

输出:[9,4]

解释:[4,9] 也是可通过的

提示:

1 <= nums1.length, nums2.length <= 1000

0 <= nums1[i], nums2[i] <= 1000

思考历程与知识点:  

题目很简单,求集合,用数组可以做,但我们尝试学习set的方法来完成。

介绍今天要学习的新东西:unordered_set.

unordered_set: 无序set, set里的值不能重复。

unordered_set用在这个去重的题目里就特别合适了,,可以直接把重复值去掉。

具体如何使用看下面题解应该就明白了。

题解:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> res; // 存放结果,之所以用set是为了给结果集去重
        unordered_set<int> nums_set(nums1.begin(), nums1.end());//把nums1再存为 unordered_set.因为vector没有find函数。
        for (int i=0;i<nums2.size();i++) {
            // 发现nums2的元素 在nums_set里又出现过
            if (nums_set.find(nums2[i]) != nums_set.end()) {
                res.insert(nums2[i]);在res结果数组中插入数字
            }
        }
        return vector<int>(res.begin(), res.end());
    }
};

题目:202题. 快乐数

Leetcode原题:202. 快乐数

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。

然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。

如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

示例 1:

输入:n = 19

输出:true

解释:

12 + 92 = 82

82 + 22 = 68

62 + 82 = 100

12 + 02 + 02 = 1

示例 2:

输入:n = 2

输出:false

提示:

1 <= n <= 231 - 1

思考历程与知识点:  

题目特意说明,可能会无限循环,也就是sum和可能相等,所以需要记录sum,当重复的时候进行退出。

题解:

class Solution {
public:
    // 取数值各个位上的单数之和
    int getSum(int n) {
        int sum = 0;
        while (n) {
            sum += (n % 10) * (n % 10);
            n /= 10;
        }
        return sum;
    }
    bool isHappy(int n) {
        unordered_set<int> set;
        while(1) {
            int sum = getSum(n);
            if (sum == 1) {
                return true;
            }
            // 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
            if (set.find(sum) != set.end()) {
                return false;
            } else {
                set.insert(sum);
            }
            n = sum;
        }
    }
};

题目:1. 两数之和

Leetcode原题链接:1. 两数之和(Leetcode的第一道题)

给定一个整数数组 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

只会存在一个有效答案

思考历程与知识点:  

如果暴力来做,两个for,时间复杂度O(N^2),这里我们还是尝试学习进行优化。

新知识点:map。

map: 可以看做是一个动态数组,类似于vector<int> a, 但是map[n] 会根据n的大小进行自动排序。n可以为int, 也可以是string等其他类型,这是数组做不到的。后续做到字符串的题时我们会用到这个特性。

创建一个空map, 并遍历一遍数组。每次都在map中找,是否有相应的数字,如果没有就把数字和对应下标加进map里,进行下一个数字的查找。

为什么不干脆先把所有的数字和下标全存进map再进行查找,而是先建立空map再一个一个的把不符话的数字存进map呢?

因为题目说了,不能包括自己。如果全部先存进map,那么遇到5+5=10这种情况,即使只有1个5,它仍然遍历成功,因为确实找到了5呀,所以为了避免这种情况,每次都先查找再加入当前数字,保证当前这个数字不会被查找到。

题解:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map <int,int> map;
        for(int i = 0; i < nums.size(); i++) {
            // 遍历当前元素,并在map中寻找是否有匹配的key
            auto iter = map.find(target - nums[i]);  
            if(iter != map.end()) {
                return {iter->second, i};
            }
            // 如果没找到匹配对,就把访问过的元素和下标加入到map中
            map.insert(pair<int, int>(nums[i], i));  
        }
        return {};
    }
};


目录
打赏
0
0
0
0
59
分享
相关文章
491.递增子序列, 46.全排列, 47.全排列 II
**简介:** 本文介绍了三道经典的回溯算法题目及其解法,分别是“491. 递增子序列”、“46. 全排列”和“47. 全排列 II”。其中,“491”要求从数组中找出所有不同的递增子序列,需注意去重且不能对原数组排序;“46”是求不含重复数字数组的所有全排列,使用布尔数组记录元素使用状态;“47”则针对含重复数字的数组求不重复的全排列,通过排序与树层去重实现。 这些题目涵盖了回溯算法中的常见问题类型,如子集、排列以及去重处理,帮助读者深入理解回溯算法的核心思想与实现细节。代码示例详细展示了如何通过递归与剪枝优化解决问题,是学习回溯算法的经典案例。
端午出游高定:通义灵码+高德 MCP 10 分钟定制出游攻略
本文介绍了如何使用通义灵码编程智能体和高德MCP 2.0制作北京端午3天旅行攻略页面。首先需下载通义灵码AI IDE并获取高德申请的key,通过添加MCP服务、生成travel_tips.html文件完成初步攻略制作。用户可自定义页面风格、固定基础功能页面生成,并扩展MCP服务以满足多样化需求。文章还详细描述了开发专属MCP服务的过程,包括借助通义灵码编写代码、部署服务及调用工具,最终实现个性化旅游攻略生成。此外,提供了相关资料和参考链接,方便读者深入了解和实践。
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发四
本文介绍了Web组件开发与性能优化的相关内容。在Web组件开发部分,涵盖创建组件、设置样式与属性、添加事件和方法以及场景示例,如动态播放视频。性能提升方面,推荐使用数据懒加载、条件渲染替代显隐控制、Column/Row替代Flex、设置List组件宽高及调整cachedCount减少滑动白块等方法,以优化应用性能与用户体验。
124 56
专家博主最新专享福利上线!发文即得积分好礼!
最新专享福利上线!赢取海量积分兑换心仪礼品
664 0
Agent 工程师绕不开的必修课:API 网关 vs API 管理
本文探讨了“API管理”与“API网关”的起源、发展及差异,二者分别服务于API生命周期的不同阶段。API网关从流量网关演进至AI网关,承担运行时请求控制;API管理则从接口文档化发展到商业化平台,关注全生命周期治理。两者在实际应用中协同工作,通过分层架构和策略联动实现高效运营。未来,随着大模型应用的兴起,AI网关和MCP Server管理将成为新趋势,推动API技术迈入智能化和服务化的新阶段。
Agent 工程师绕不开的必修课:API 网关 vs API 管理
704.二分查找、27.移除元素
### 704. 二分查找 题目要求在有序数组中查找目标值,若存在则返回下标,否则返回 -1。通过二分查找实现,时间复杂度为 O(log n)。关键点在于正确计算中间索引 `mid`,并避免溢出。提供了 C++、Java 和 Python 的实现代码。 ### 27. 移除元素 题目要求原地移除数组中所有等于指定值的元素,并返回新数组长度。使用快慢指针法,将不等于目标值的元素移动到数组前部,从而实现 O(1) 空间复杂度的要求。同样提供了 C++、Java 和 Python 的实现代码。 两题均注重算法效率与空间优化,适合初学者练习基础算法思想。
977.有序数组的平方、209.长度最小的子数组、 59.螺旋矩阵II
1. **997. 有序数组的平方**:给定非递减顺序的整数数组,返回每个数字平方后的新数组,要求结果仍为非递减顺序。提供了两种解法——使用`sort()`函数和双指针法,后者利用原数组有序特性优化时间复杂度。 2. **209. 长度最小的子数组**:寻找和大于等于目标值的最短连续子数组长度。采用滑动窗口(毛毛虫比喻)方法,在O(n)时间内完成任务,通过动态调整窗口大小实现高效求解。 3. **59. 螺旋矩阵 II**:生成一个按顺时针螺旋排列的n×n矩阵。通过模拟填充过程,依次向右、下、左、上四个方向扩展边界,直至填满整个矩阵。
24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交
1. **两两交换链表中的节点**:通过引入虚拟头结点,使所有节点都能采用统一的交换逻辑,避免对头结点单独处理。 2. **删除链表的倒数第N个节点**:利用双指针技巧,让快慢指针保持N个节点的距离,当快指针到达末尾时,慢指针正好指向待删除节点的前一个节点。 3. **链表相交**:先计算两链表长度并调整起点,确保从相同距离末尾的位置开始遍历,从而高效找到相交节点或确定无交点。 以上方法均在时间复杂度和空间复杂度上进行了优化,适合用于理解和掌握链表的基本操作及常见算法设计思路。
454.四数相加II , 383. 赎金信 ,15. 三数之和 , 18. 四数之和
1. **454. 四数相加II**:通过哈希表优化暴力解法,将问题分为两部分处理,时间复杂度从O(n^4)降至O(n^2)。 2. **383. 赎金信**:利用数组统计字符频率,判断子串是否能由母串构成,时间复杂度为O(n)。 3. **15. 三数之和**:借助排序与双指针技巧,将三重循环优化至双重循环,时间复杂度为O(n^2)。 4. **18. 四数之和**:在三数之和的基础上扩展,增加一层循环并结合剪枝操作,避免重复解,时间复杂度仍为O(n^3)。 这些题目展示了哈希表、双指针和排序等常用算法技巧的应用,适合巩固基础与提升解题能力。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等