【leetcode】双“指针”

 标题:【leetcode】双指针

水墨不写bug

我认为 讲清楚为什么要用双指针 比讲怎么用双指针更重要


(一)快乐数


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

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

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

示例 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

示例 2:

输入:n = 2
输出:false

提示:

  • 1 <= n <= 2^31 - 1

题解:

        记快乐数转换的对应关系为f,每一次对应关系f处理后,相当于指针向后移动一次;

        由于一个数被 f  对应关系的映射后得到数的过程是不可逆转的-->【100 的得到方法不止一种:f(68) = 100;f(86) = 100, 所以知道f处理后的结果是100,但是无法确定f处理的源(原)数是谁】

        根据这一特征,我们可以想象一个数据结构,它类似于单链表,由此可以联想到我们之前已经做过的问题:

        链表是否成环 :链表可以仅仅是一条单链,也可以是像 “6” 一样链表,当环达到最大时,链表就成了 “0” 形。

        本题  可以 类比 判断链表是否有环 的思路,但是一种情况可以忽略:一条单链表。

为什么可以忽略?

在这条“链表”中,只可能存在 “1” 或者不存在 “1” 两种情况。

        如果存在“1”,由于对“1”进行 f 对应关系的映射后仍然等于 “1”,于是 “1” 单独成环

        如果不存在 “1”,对任意一个数,都可经过有限次f变换后得到它本身。

        (现在证明:对任意一个数,都可经过有限次f变换后得到它本身。

                   int类型的范围的数量级是10^9级【10亿级】,最大的int值小于9999999999,这个值经过f变换后得到的值——9^2+9^2+9^2+9^2+9^2+9^2+9^2+9^2+9^2=729;

由于规定的输入为正整数,这意味着f的值域为[1,729],考虑到整数平方后得到的结果一定是整数,所以一个数经过最多729次变换后,它的取值取便了[1,729]的任意值,如果再进行一次f变换,得到的结果一定会与之前的值重复,命题的证。)

 为什么选择双指针?

        经过分析,可以知本题的数据结构是一个 “6” 形的 “链表”,正常的遍历无法得到终止,根据  链表是否成环 的经验,可以想到用快慢指针的速度差来判断,如果在“链表中存在 “1””,那么两指针会在“1”相遇;否则,两指针会在环中的一个随机位置相遇。

(具体实现f函数名称为Bitsum) 

class Solution {
public:
    
    //实现思路:取到这个数的每一位,平方后加到sum中;
    int Bitsum(int n)
    {
        int sum = 0;
        while(n)
        {
            int t = n%10;
            sum += t*t;         
            n/=10;
        }
        return sum;
    }

    bool isHappy(int n) {
        int slow = n,fast = Bitsum(n);
        while(slow!=fast)
        {
            slow = Bitsum(slow);
            fast = Bitsum(Bitsum(fast));
        }
    return slow == 1;
    }
};

(二)盛水最多的容器


        给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

        找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

        返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例 1:

输入:[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 <= 10^5
  • 0 <= height[i] <= 10^4

如果解决一道题?

        首先,我会先理解这道题,通过分析示例,彻底理解题目的要求;

        其次,我最先想到的是暴力求解,为什么?通过分析历年大赛的标准答案解法,最优解法往往是在暴力求解的基础上,优化暴力求解来得到的。优先考虑暴力解法,再通过优化暴力求解算法来得到更优的算法;另外,对于暴力求解算法,一些特殊测试点往往是会超时的,没有办法得到高分;

        然后,分析时我发现这道题可以利用双指针来避免一些不必要的枚举结果,也就是上述的优化——优化是从多种层面的,需要一些经验积累。

        最后,自己写一些测试点和结果,对照写好的程序,在纸上一步一步走读代码;这些测试点的选取要考虑全面,防止漏情况。

        根据暴力求解算法,可以在数组中选择两个下标不重复的数,用较小的数 * 两数下标之差就是体积V,记录所有的V,最终返回最大的V即可;

        固定一个下标(left),让另一个下标(right)向右遍历,遍历完后,left++,类推;

我们把本题抽象为桶:

         既然存储最多的水,我们我们直接在遍历的过程中舍去 “短板”不就行了吗?留下最长的两个板,得到的结果V不就是最大的吗?

{               

                if(height[left] >= height[right])
                       right--;
                else
                       left++;

}

        这是有人会有疑问,板长了,但是不能保证宽度大啊,V要大,前提是痛的桶壁板子和桶的内径都很大。

        确实是这样的,但是不要忘了,我们还有这两句:

 {

                int v = min(height[left],height[right])*(right-left);
                ret = max(ret,v);

}

        由于ret在每次变更桶壁后都会更新,并且会选择较大的V覆盖原值;

        那么,就相当于在 不断增长桶壁的同时也可保存V在一系列变化中的最大值;

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])
                right--;
            else
                left++;
        }
        return ret;
    }
};

(三)有效三角形个数

给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。

示例 1:

输入: nums = [2,2,3,4]
输出: 3
解释:有效的组合是: 
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3

示例 2:

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

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000
class Solution {
public:

static int my_cmp(const void*a,const void*b)
{
    return *((int*)a) - *((int*)b);
}
    int triangleNumber(vector<int>& nums)
    {
        int count = 0;
        int pmax = nums.size()-1,left = 0,right = pmax - 1;
        
        qsort(&nums[0],nums.size(),sizeof(nums[0]),my_cmp);
        for(; pmax>=2 ;pmax--)
        {
            left = 0,right = pmax - 1;
            while(left < right)
            {
                if(nums[left] + nums[right] > nums[pmax]) 
                    {count +=(right-left);--right;}
                else {++left;}
            }
        }
        
        return count;
    }
};

(四)总和为目标值的两个数

购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况,返回任一结果即可。

示例 1:

输入:price = [3, 9, 12, 15], target = 18
输出:[3,15] 或者 [15,3]

示例 2:

输入:price = [8, 21, 27, 34, 52, 66], target = 61
输出:[27,34] 或者 [34,27]

提示:

  • 1 <= price.length <= 10^5
  • 1 <= price[i] <= 10^6
  • 1 <= target <= 2*10^6
class Solution {
public:
    vector<int> twoSum(vector<int>& price, int target) {
        
        int left = 0,right = price.size()-1;
        while(1)
        {
            int sum = price[right] + price[left];
            if( sum> target) right--;
            else if(sum < target) left++;
            else break;
        }
        vector<int> it = {price[left],price[right]};
        return it;
    }
};

完~

未经作者同意禁止转载

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity 窗口化设置

在Unity中要实现窗口化&#xff0c;具体设置如下&#xff1a; 在编辑器中&#xff0c;选择File -> Build Settings。在Player Settings中&#xff0c;找到Resolution and Presentation部分。取消勾选"Fullscreen Mode"&#xff0c;并选择"Windowed"。设…

Linux:Jenkins:参数化版本回滚(6)

上几章我讲到了自动集成和部署 Linux&#xff1a;Jenkins全自动持续集成持续部署&#xff08;4&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136977106 当我们觉得这个页面不行的时候&#xff0c;需要进行版本回滚&#xff0c;回滚方法我这里准备了…

Linux 反引号、单引号以及双引号的区别

1.单引号—— 单引号中所有的字符包括特殊字符&#xff08;$,,和\&#xff09;都将解释成字符本身而成为普通字符。它不会解析任何变量&#xff0c;元字符&#xff0c;通配符&#xff0c;转义符&#xff0c;只被当作字符串处理。 2.双引号——" 双引号&#xff0c;除了$,…

LangSAM项目优化,将SAM修改为MoblieSAM,提速5~6倍

Language Segment-Anything 是一个开源项目&#xff0c;它结合了实例分割和文本提示的强大功能&#xff0c;为图像中的特定对象生成蒙版。它建立在最近发布的 Meta 模型、segment-anything 和 GroundingDINO 检测模型之上&#xff0c;是一款易于使用且有效的对象检测和图像分割…

定时任务 之 cron 表达式

Cron 表达式产生的背景&#xff1a;在Unix系统中&#xff0c;用户经常需要设置一些周期性被执行的任务&#xff0c;如定期备份文件、发送邮件等。为了满足这种需求&#xff0c;Unix系统提供了crontab命令&#xff0c;允许用户定义任务的时间表&#xff0c;并在指定的时间点自动…

实现实时查询并带有查询结果列表的输入框

这个功能主要是实现了一个可以实时查询结果的搜索框&#xff0c;并具备点击外部关闭搜索结果框体的功能&#xff0c;除了v-show和transition依托于vue实现以外其余功能都基于原生JS实现。 效果图&#xff1a; 该功能的实现主要是很久之前面试被问到过&#xff0c;当时没有做出…

Linux:进程控制

进程创建 进程&#xff1a;内核的相关管理数据结构&#xff08;task_structmm_struct页表&#xff09;代码&#xff08;<-共享&#xff09;和数据(<-写时拷贝) fork函数初识 在 linux 中 fork 函数时非常重要的函数&#xff0c;它从已存在进程中创建一个新进程。新进程…

1992-2022年经过矫正的夜间灯光数据

DMSP/OLS夜间灯光的年份是1992-2013年&#xff0c;NPP/VIIRS夜间灯光的年份是2012-2021&#xff0c;且由于光谱分辨率、空间分辨率、辐射分辨率、产品更新周期等方面的差异&#xff0c;DMSP-OLS和SNPP-VIIRS数据不兼容&#xff0c;也就是说我们无法直接对比分析DMSP-OLS和SNPP-…

Linux常用命令-文件操作

文章目录 ls基本用法常用选项组合选项示例注意事项 cd基本用法示例注意事项 pwd基本用法示例选项总结 cp基本用法常见选项示例注意事项 rm基本用法常见选项示例删除单个文件&#xff1a;交互式删除文件&#xff1a;强制删除文件&#xff1a;递归删除目录&#xff1a;交互式递归…

实验02-1 C#和ASP.NET控件:在Web窗体中输出九九乘法表

【实验内容及要求】 1. 在Web窗体中输出九九乘法表 浏览效果如图2-1所示。 图2-1 在Default.aspx.cs中编写C#代码 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls;public par…

项目四-图书管理系统

1.创建项目 流程与之前的项目一致&#xff0c;不再进行赘述。 2.需求定义 需求: 1. 登录: ⽤⼾输⼊账号,密码完成登录功能 2. 列表展⽰: 展⽰图书 3.前端界面测试 无法启动&#xff01;&#xff01;&#xff01;--->记得加入mysql相关操作记得在yml进行配置 配置后启动…

操作系统系列学习——多级页表与快表

文章目录 前言多级页表与快表 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招&#xff0c;计划学习操作系统并完成6.0S81&#xff0c;加油&#xff01; 本文总结自B站【哈工大】操作系统 李治军&#xff08;全32讲&#xff09; 老师课程讲的非常好&#xff0c;感谢 【哈工…

PythonGUI应用:模拟航空订票小程序

在本教程中&#xff0c;我们将创建一个基本的航空订票管理系统GUI应用&#xff0c;用户可以通过图形界面执行各种操作。我们将使用Python编程语言和Tkinter库来实现此应用。 功能概述&#xff1a; 航班管理&#xff1a; 用户可以添加新的航班&#xff0c;输入航班号、起始地、目…

Convex and Semi-Nonnegative Matrix Factorizations

我们提出了非负矩阵分解&#xff08;NMF&#xff09;主题的几种新变体。考虑形式为X FG^T的因子分解&#xff0c;我们关注的是G被限制为包含非负元素的算法&#xff0c;但允许数据矩阵X具有混合符号&#xff0c;从而扩展了NMF方法的适用范围。我们还考虑了基向量F被约束为数据…

Ubuntu20.04更换镜像源------最简单的教程

本教程适用于&#xff1a;Ubuntu22.04 操作流程 打开终端&#xff0c;运行以下命令&#xff1a; sudo sed -i "shttp://.*archive.ubuntu.comhttps://mirrors.tuna.tsinghua.edu.cng" /etc/apt/sources.list 运行后即完成更改。 如果找不到22.04的镜像&#xff…

海外盲盒APP:加速开拓海外盲盒市场

盲盒是年轻群体消费中增速较快的模式&#xff0c;从前几年起&#xff0c;盲盒就在我国掀起了一股热潮&#xff0c;市场得到了迅速发展。 如今&#xff0c;盲盒经济已经遍布到了全球&#xff0c;尤其是在亚洲地区&#xff0c;盲盒消费呈现出了高速发展态势&#xff0c;在海外市…

支小蜜校园防霸凌系统的具体功能是什么?

在当今社会&#xff0c;校园霸凌问题日益严重&#xff0c;成为影响学生健康成长的一大隐患。为了应对这一问题&#xff0c;许多学校开始引入校园防霸凌系统。这一系统以其独特的功能&#xff0c;为校园安全提供了有力保障&#xff0c;为学生的健康成长创造了良好环境。 校园防…

蓝桥杯单片机快速开发笔记——PCF8591的DAC模拟电压输出

一、原理分析 PCF8591电压信号探测器&#xff1a;http://t.csdnimg.cn/R38tC IIC原理&#xff1a;http://t.csdnimg.cn/v4dSv IIC指令&#xff1a;http://t.csdnimg.cn/RY6yi HC573/HC138&#xff1a;http://t.csdnimg.cn/W0a0U 数码管&#xff1a;http://t.csdnimg.cn/kfm9Y 独…

反序列化动态调用 [NPUCTF2020]ReadlezPHP1

在源代码上看到提示 访问一下看看 代码审计一下 <?php #error_reporting(0); class HelloPhp {public $a;public $b;public function __construct(){$this->a "Y-m-d h:i:s";$this->b "date";}public function __destruct(){$a $this->a;…

编译安装飞桨fastdeploy@FreeBSD(失败)

FastDeploy是一款全场景、易用灵活、极致高效的AI推理部署工具&#xff0c; 支持云边端部署。提供超过 &#x1f525;160 Text&#xff0c;Vision&#xff0c; Speech和跨模态模型&#x1f4e6;开箱即用的部署体验&#xff0c;并实现&#x1f51a;端到端的推理性能优化。包括 物…
最新文章