【算法专题--双指针算法】leecode-202. 快乐数(medium)、leecode-11. 盛最多水的容器(medium)

这篇具有很好参考价值的文章主要介绍了【算法专题--双指针算法】leecode-202. 快乐数(medium)、leecode-11. 盛最多水的容器(medium)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


【算法专题--双指针算法】leecode-202. 快乐数(medium)、leecode-11. 盛最多水的容器(medium),算法
🍁你好,我是 RO-BERRY
📗 致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识
🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油

【算法专题--双指针算法】leecode-202. 快乐数(medium)、leecode-11. 盛最多水的容器(medium),算法



前言

双指针
常见的双指针有两种形式,一种是对撞指针,⼀种是左右指针。
对撞指针:一般用于顺序结构中,也称左右指针。

  • 对撞指针从两端向中间移动。一个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼
    近。
  • 对撞指针的终止条件一般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出循
    环),也就是:
    • left == right (两个指针指向同一个位置)
    • left > right (两个指针错开)

快慢指针:又称为龟兔赛跑算法,其基本思想就是使用两个移动速度不同的指针在数组或链表等序列
结构上移动。
这种方法对于处理环形链表或数组非常有用。
其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使用快
慢指针的思想。

快慢指针的实现方式有很多种,最常用的⼀种就是:

  • 在一次循环中,每次让慢的指针向后移动一位,而快的指针往后移动两位,实现一快一慢。

1. 快乐数(medium)

题目描述:
编写一个算法来判断一个数 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

2. 解法

思路:
可以把题目中的两种情况当成一种情况来看,就是一直在死循环

  1. 对于情况一:⼀直在 1 中死循环
  2. 对于情况二:在历史的数据中死循环,但始终变不到 1

为什么会死循环?

题目所给数据范围是小于整型(int)的最大值 231-1=2147483647,这里我们们不难发现最大值的位数是 10,那么我们可以用一个十位数的最大值来变换,即 9999999999,那么它经过变换得到的值就是 92 * 10 = 810 ,那么经过所有变换的结果就会在区间 [1, 810] 之间;
根据【鸽巢原理】,⼀个数变化 811 次之内,必然会在一个循环中有重复。
因此,可以⽤「快慢指针」来解决。

解题方法:

  1. ProductSum 函数:
  • 这个函数计算一个整数的每个位上数字的平方和。
  • 通过不断地对整数取模 10 来获取其最后一位数字,然后将其平方并累加到 sum 变量中。
  • 每次迭代,整数都通过整除 10 来移除最后一位数字。
  • 当整数变为 0 时,函数返回累加的和 sum。
  1. isHappy 函数:
  • 使用“快慢指针”技术来检测循环。
  • slow 和 fast 初始时都指向 n。
  • slow 每次移动一步,即计算当前数字的平方和。
  • fast 每次移动两步,即连续计算两次平方和。
  • 如果 n 是一个快乐数,slow 和 fast 最终都会达到 1。
  • 如果 n 进入循环,slow 和 fast 会在循环中的某个点相遇(即它们的值相等)。
  • 如果 slow 和 fast 相等且等于 1,则 n 是快乐数。
  • 算法中使用了 do-while 循环而不是 while 循环,以确保至少执行一次循环体(即至少计算一次ProductSum),即使 slow 和 fast 初始时就相等。

复杂度

时间复杂度: O(logN)
空间复杂度: O(1)

C++算法代码:

class Solution {
public:
    int ProductSum(int n)
    {
        int sum = 0;
        while(n)
        {
            int temp = n % 10;
            sum += temp*temp;
            n /= 10;
        }
        return sum;
    }

    bool isHappy(int n) {
        int slow = n,fast = n;
        // 快慢指针,找环的相遇位置
        do
        {
            slow = ProductSum(slow);
            fast = ProductSum(ProductSum(fast));
        }while(slow != fast);
        // 如果相遇时是 1 就是快乐数
        return slow == 1;
    }
};

【算法专题--双指针算法】leecode-202. 快乐数(medium)、leecode-11. 盛最多水的容器(medium),算法
java算法代码:

class Solution
{
	public int bitSum(int n) // 返回 n 这个数每⼀位上的平⽅和
	{
		int sum = 0;
		while (n != 0)
		{
			int t = n % 10;
			sum += t * t;
			n /= 10;
		}
		return sum;
 	}
 	public boolean isHappy(int n)
 	{
		 int slow = n, fast = bitSum(n);
		 while (slow != fast)
		{
			 slow = bitSum(slow);
			 fast = bitSum(bitSum(fast));
		 }
	 return slow == 1;
	 }
}

【算法专题--双指针算法】leecode-202. 快乐数(medium)、leecode-11. 盛最多水的容器(medium),算法

3. 盛水最多的容器(medium)

题目描述:

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。

示例 1:
【算法专题--双指针算法】leecode-202. 快乐数(medium)、leecode-11. 盛最多水的容器(medium),算法

输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:

输入:height = [1,1]
输出:1

提示:

n == height.length
2 <= n <= 105
0 <= height[i] <= 104

4. 解法

解法一(暴力求解)(会超时):

算法思路:
枚举出能构成的所有容器,找出其中容积最大的值。

容器容积的计算方式:
设两指针 i , j,分别指向水槽板的最左端以及最右端,此时容器的宽度为j - i
容器的高度由两板中的短板决定,因此可得容积公式︰v = (j - i) * min(height[il, height[j])

算法代码:

class Solution {
public:
	int maxArea(vector<int>& height) {
		int n = height.size();
		int ret = 0;
		// 两层 for 枚举出所有可能出现的情况
		for (int i = 0; i < n; i++) {
			for (int j = i + 1; j < n; j++) {
				// 计算容积,找出最⼤的那⼀个
				ret = max(ret, min(height[i], height[j]) * (j - i));
			}
		}
		return ret;
	}
};

解法二(对撞指针):

算法思路:
设两个指针 left , right 分别指向容器的左右两个端点,此时容器的容积 : v = (right - left) * min( height[right], height[left])
容器的左边界为height[left],右边界为 height[right]
为了方便叙述,我们假设「左边边界」小于「右边边界」. 如果此时我们固定一个边界,改变另一个边界,水的容积会有如下变化形式:

  • 容器的宽度⼀定变小
  • 由于左边界较小,决定了⽔的⾼度.如果改变左边界,新的水面高度不确定,但是⼀定不会超过右边的柱子高度,因此容器的容积可能会增大.
  • 如果改变右边界,无论右边界移动到哪里,新的水面的高度⼀定不会超过左边界,也就是不会超过现在的水面高度,但是由于容器的宽度减小,因此容器的容积⼀定会变小的.
  • 由此可见,左边界和其余边界的组合情况都可以舍去.所以我们可以 left++ 跳过这个边界,继续去判断下⼀个左右边界.

当我们不断重复上述过程,每次都可以舍去⼤量不必要的枚举过程,直到 left 与 right 相 遇.期间产生的所有的容积里面的最大值,就是最终答案.

C++ 算法代码:

class Solution
{
public:
	int maxArea(vector<int>& height)
	{
		int left = 0, right = height.size() - 1, ret = 0;
		while (left < right)
		{
			int v = min(height[left], height[right]) * (right - left);
			ret = max(ret, v);
			// 移动指针
			if (height[left] < height[right]) left++;
			else right--;
		}
		return ret;
	}
};

【算法专题--双指针算法】leecode-202. 快乐数(medium)、leecode-11. 盛最多水的容器(medium),算法
Java 算法代码:文章来源地址https://www.toymoban.com/news/detail-842776.html

class Solution
{
	public int maxArea(int[] height)
	{
		int left = 0, right = height.length - 1, ret = 0;
		while (left < right)
		{
			int v = Math.min(height[left], height[right]) * (right - left);
			ret = Math.max(ret, v);
			if (height[left] < height[right]) left++;
			else right--;
		}
		return ret;
	}
}

到了这里,关于【算法专题--双指针算法】leecode-202. 快乐数(medium)、leecode-11. 盛最多水的容器(medium)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【算法专题突破】双指针 - 盛最多水的容器(4)

    目录 1. 题目解析 2. 算法原理 3. 代码编写 写在最后: 题目链接:11. 盛最多水的容器 - 力扣(Leetcode)   这道题目也不难理解, 两边的柱子的盛水量是根据短的那边的柱子决定的, 而盛水量就是短的柱子的高度 * 宽度即可。  这道题可以用暴力枚举,两层for循环,肯定是可

    2024年02月10日
    浏览(28)
  • 【算法专题突破】双指针 - 快乐数(3)

    目录 1. 题目解析 2. 算法原理 3. 代码编写 写在最后: 题目链接:202. 快乐数 - 力扣(Leetcode) 这道题的题目也很容易理解, 看一下题目给的示例就能很容易明白, 但是要注意一个点,最后有可能无限循环无法到达1。 这个时候我们就要想一下怎么判断他是无线循环呢? 实际

    2024年02月11日
    浏览(26)
  • 【算法——双指针】LeetCode 11 盛最多水的容器

    题目描述: 解题思路:         如图所示:         1、我们考虑相距最远的两个柱子所能容纳水的面积。宽度是两根柱子之间的距离8;高度取决于两根柱子之间较短的那个,即左边柱子的高度3。水的面积就是3×8=24。         2、如果选择固定一根柱子,另外一根

    2024年02月12日
    浏览(22)
  • 【算法|双指针系列No.4】leetcode11. 盛最多水的容器

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成长,共同进步。

    2024年02月06日
    浏览(38)
  • 力扣-202. 快乐数解析-弗洛伊德循环查找算法

    题目链接   使用代码测试一下每一代数字  可以发现 归纳一下这些简单数字就可以发现,对于任意一个非快乐数,最终会进入重复循环, ···不难发现,4即之后的结果就是新一轮循环。 那么我的第一个做法是检测4出现的次数 如果4出现次数超过两次, 那么就不是快乐数 感

    2024年01月20日
    浏览(28)
  • 【算法】双指针求解盛最多水的容器

    Problem: 11. 盛最多水的容器 首先我们来解析一下本题 题目中说到,要找出其中的两条线, 使得它们与 x 轴共同构成的容器可以容纳最多的水 。 那我们现在来看最外侧的两根,一个高度为8,一个则为7,那我们肯定选择高度为7的, 如果选择8的话就会出现溢出的问题 ;我们这

    2024年02月11日
    浏览(31)
  • 算法训练第5天|哈希表理论基础 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

    哈希表是根据 关键码 的值而直接进行访问的数据结构。 一般哈希表都是用来快速判断一个元素是否出现集合里。 数组、集合set、映射map 力扣链接 题目描述: 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 注意: 若  s  和  t   中每个字符出现的

    2024年02月19日
    浏览(34)
  • 【算法】双指针——leetcode盛最多水的容器、剑指Offer57和为s的两个数字

    盛水最多的容器 (1)暴力解法   算法思路:我们枚举出所有的容器大小,取最大值即可。   容器容积的计算方式:   设两指针 i , j ,分别指向水槽板的最左端以及最右端,此时容器的宽度为 j - i 。由于容器的高度由两板中的较短的板决定,因此可得容积公式 :

    2024年02月13日
    浏览(37)
  • 【力扣算法12】之 11. 盛最多水的容器 python

    给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明 :你不能倾斜容器。 输入:[1,8,6,2,5,4,8,3,7] 输出:49 解释:图中垂

    2024年02月16日
    浏览(38)
  • LeetCode 202 快乐数

    力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 使用哈希表循环判断每次经过平方和的数,如果为1则直接返回true,若之前存在过但不为1则直接返回false 判断相遇的时候是否为1,若不为1则返回false,若为1则返回true

    2024年02月09日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包