【优选算法篇】--双指针篇


欢迎来到我的博客园

一、有效三角形的个数

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

在这里插入图片描述


解析:
能否组成三角形,满足任意两边之和大于第三边,大家可能会想到暴力解法。这里提供个最优解法。
对于一组已经排好序的数来说,如果a>=b>=c,则只需b+c>a.
先确定一个最大的数a,再定义left right指针,left指针指向0,right指向最大数的前一位,如果满足左右指针指向的数大于a,那么能组成三角形有效个数就是right-left,这是因为左边第一个数加右边数大于最大数了,中间数肯定比左边第一个数大,那么肯定也满足
在这里插入图片描述

代码篇:

class Solution {
public:
    int triangleNumber(vector<int>& num) {
        //先排序
        sort(num.begin(),num.end());

        int ret=0,n=num.size();
        //系咱固定最大的数,用i来固定
        for(int i=n-1;i>=2;i--)
        {
            //双指针循环
            int left=0,right=i-1;
            while(left<right)
            {
                if(num[left]+num[right]>num[i])
                {
                    ret+=right-left;
                    right--;
                }
                else{
                    left++;
                }
            }
        }
        return ret;
    }
};

二、快乐数

题目;
原题链接

编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:

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

在这里插入图片描述


解析:
这里分两种情况,一种是直接到1,另一种是不会到1(这种会会形成一个环,一直循环下去),如图所示,直接到1的其实也可以看成一个环,只不过换里面全是1,这是我们使用快慢指针的思想,慢指针走一步,快指针走两步,知道相遇即可,并判断相遇位置是否等于1就行。
在这里插入图片描述


代码:

class Solution {
public:
    
    int bitsum(int n)  //返回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]
输出:


解析:
首先我们先理解下题目含义,在第i位置处高度为height[i],最终求最大容量,俩条线之间的最大面积。用暴力枚举会超时,这里使用双指针算法思想。
让左右指针分别从左、右两端进行移动,每移动一次计算他俩之间的面积,最终求面积最大的即可。(移动过程中需注意,谁小谁移动)。


代码:

class Solution {
public:
    int maxArea(vector<int>& height) {
        int left=0,right=height.size()-1,ret=0;
        //左右指针在移动着,结束条件就是他俩相遇
        while(left<right)
        {
            //v计算容积
            int v=min(height[left],height[right])*(right-left);
            ret=max(ret,v);//ret记录最大的
            //谁小谁移动
            if(height[left]<height[right]) left++;
            else    right--;
        }
        return ret;
    }
};

总结:
以上就是本篇内容,欢迎大家在评论区讨论交流。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值