🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟
别再犹豫了!快来订阅我们的算法每日双题精讲专栏,一起踏上算法学习的精彩之旅吧!💪
目录
💯前言
💯快乐数
题目描述:
⭐解题思路:
🙋这个解题思路是怎么来的呢?
代码实现(C++为例):
👀时间复杂度和空间复杂度
💯盛最多水的容器
题目描述:
⭐解题思路:
🙋这个解题思路是怎么来的呢?
代码实现(C++为例):
👀时间复杂度和空间复杂度
💯总结
💯前言
在算法的奇妙世界里,双指针技巧宛如一把神奇的钥匙,能够开启许多难题的解决之门😎。
今日,就让我们一同深入探究两道借助双指针策略破解的经典题目:快乐数与盛最多水的容器。
📣由于俩道题目均为数组,这里的双指针算法指的是:利用数组下标代替指针
当我们遇到,数组分块,数组划分的问题时,可以考虑使用双指针法。
💯快乐数
题目链接👉【力扣】
题目描述:
编写一个算法来判断一个数 n
是否为 “快乐数”。
“快乐数” 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,
- 然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。
- 如果这个过程结果为 1,那么这个数就是快乐数。
示例:
- 输入:
n = 19
- 输出:
true
- 解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
⭐解题思路:
我们可以使用双指针法来解决这个问题。定义一个快指针 fast
和一个慢指针 slow
,初始时都指向数字 n
。快指针每次计算下一个数时,会连续计算两次平方和,而慢指针每次只计算一次。通过不断重复这个过程,如果快指针等于 1,说明该数是快乐数;如果快指针等于慢指针且不等于 1,说明进入了循环,该数不是快乐数。
🙋这个解题思路是怎么来的呢?
我们进行画图:
我们发现该题目像极了,环问题,因此我们的解题思路为快慢指针。
代码实现(C++为例):
class Solution {
public:// 计算整数 n 各个数位上数字的平方和int sumN(int n) {int sum = 0;// 循环计算每个数位上数字的平方和while (n!= 0) {int t = n % 10; // 取出 n 的最后一位数字sum += t * t; // 将该数字的平方累加到 sum 中n = n / 10; // 去掉 n 的最后一位数字}return sum;}// 判断整数 n 是否为快乐数bool isHappy(int n) {int slow = n; // 慢指针,初始值为输入的整数 nint fast = sumN(n); // 快指针,初始值为 n 的各个数位数字平方和// 使用快慢指针法检测是否存在循环while (slow!= fast) {slow = sumN(slow); // 慢指针每次移动一步fast = sumN(sumN(fast)); // 快指针每次移动两步}return slow == 1; // 如果慢指针等于 1,则说明 n 是快乐数}
};
👀时间复杂度和空间复杂度
时间复杂度:
- 计算单个数字的数位平方和的时间复杂度为 ,因为数字的位数与 成正比。
- 在
isHappy
函数中,使用快慢指针法来判断是否为快乐数,在没有循环的情况下,时间复杂度取决于达到 1 的步数,最多不会超过 。如果存在循环,时间复杂度也不会超过 ,因为每次计算数位平方和都会使数字减小,最终会收敛到一个较小的范围。空间复杂度:
- 代码中只使用了有限的几个变量,不随输入规模增长,所以空间复杂度为 。
💯盛最多水的容器
题目链接👉【力扣】
题目描述:
给定 n
个非负整数 a1,a2,...,an
,每个数代表坐标中的一个点 (i, ai)
。在坐标内画 n
条垂直线,垂直线 i
的两个端点分别为 (i, ai)
和 (i, 0)
。找出其中的两条线,使得它们与 x
轴共同构成的容器可以容纳最多的水。
示例:
- 输入:
height = [1,8,6,2,5,4,8,3,7]
- 输出:
49
- 解释:图中垂直线代表输入数组
height
。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为49
。
⭐解题思路:
使用双指针法,一个指针指向数组的开头 left
,一个指针指向数组的末尾 right
。计算当前指针所构成容器的面积,面积等于两指针之间的距离乘以较小的高度 min(height[left], height[right])
。然后根据高度大小移动指针,如果 height[left] < height[right]
,则将left
指针向右移动一位;否则将 right
指针向左移动一位。重复这个过程,不断更新最大面积,直到 left
和 right
指针相遇。
🙋这个解题思路是怎么来的呢?
当宽度下降时,我们只要找高度比原来高的来计算新的体积 ,进行比较,找出最大的体积
我们画图如下:
此时宽度最长
left<right,我们让left++
right<left,我们让right--
以此类推,直到left==right
代码实现(C++为例):
class Solution {
public:// 计算给定高度数组中容器的最大盛水量int maxArea(vector<int>& height) {int left = 0; // 左指针,初始指向数组首位置int right = height.size() - 1; // 右指针,初始指向数组尾位置int V = (right - left) * min(height[left], height[right]); // 初始盛水量while (left < right) {if (height[left] < height[right]) {left++; // 如果左指针指向的高度较小,左指针右移} else {right--; // 如果右指针指向的高度较小,右指针左移}int newV = (right - left) * min(height[left], height[right]); // 新的盛水量V = max(V, newV); // 更新最大盛水量}return V;}
};
👀时间复杂度和空间复杂度
时间复杂度:
- 由于只需要对数组进行一次遍历,所以时间复杂度为 ,其中
n
是数组的长度。空间复杂度:
- 代码中只使用了有限的几个变量,不随输入规模增长,所以空间复杂度为 。
💯总结
通过对快乐数和盛最多水的容器这两道题目的深入剖析,我们清晰地领略到了双指针算法在解决不同类型数组问题时所展现出的独特魅力与强大效能👏。它能够帮助我们巧妙地规避复杂的嵌套循环,以简洁高效的方式找到问题的答案。希望大家在今后的算法学习征程中,能够灵活运用双指针技巧,犹如掌握了一把锐利的武器,轻松攻克更多复杂的算法难题💪。
我将持续在算法领域深耕细作,为大家带来更多精彩的算法知识讲解与问题解析。欢迎大家关注我
👉【A Charmer】