【优选算法】双指针

在这里插入图片描述

目录

  • 一、[移动零](https://leetcode.cn/problems/move-zeroes/description/)
  • 二、[复写零](https://leetcode.cn/problems/duplicate-zeros/description/)
  • 三、[快乐数](https://leetcode.cn/problems/happy-number/)
  • 四、 [盛最多水的容器](https://leetcode.cn/problems/container-with-most-water/description/)
  • 五、[有效三角形的个数](https://leetcode.cn/problems/valid-triangle-number/description/)
  • 六、[查找总价格为目标值的两个商品](https://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/description/)
  • 七、[三数之和](https://leetcode.cn/problems/3sum/description/)
  • 八、[四数之和](https://leetcode.cn/problems/4sum/description/)
  • 结尾

一、移动零

题目描述
在这里插入图片描述


思路讲解
定义两个变量cur和prev来将数组分为三个区间,[0元素范围区间][非0元素范围区间][待处理区间],prev指向非0元素范围区间中最后一个非0元素,cur 遍历数组,找到非0元素,找到后与prev后面一个元素进行交换,直到cur将数组完全遍历完,则完成本题。


编写代码

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int prev = -1 , cur = 0;
        // prev指向非0元素范围区间中最后一个非0元素
        // cur 遍历数组,找到非0元素
        // prev 和 cur 的作用是将 num 分为三段
        
        while(cur < nums.size())
        {
            if(nums[cur] != 0)
            {
                swap(nums[++prev],nums[cur]);
            }
            // 无论是否交换cur都需要++
            cur++;
        }
    }
};

二、复写零

题目描述
在这里插入图片描述


思路讲解
本道题的要求是在原数组的要求下完成,那么这道题会变得不是非常的简单。
这里使用双指针的方法从左往右开始复写,遇到非零元素则复写一个非零元素,遇到为零的元素则复写两个零,但是从下图中我们发现只要遇到一个零就会导致后面所有的数字全部出现问题,那么下面我们换一个思路。

在这里插入图片描述

这里双指针从左向右开始复写行不通,那么这里使用从右向左开始复写试试。

当从右向左开始复写我们首先要解决的问题是从哪个元素开始从后往前,并且会出现凑巧复写两个零时只有一个位置能够复写,那么就会出现越界的问题。

下面一张图片左右两边是分别关于非越界和越界两种情况种查找的过程。

在这里插入图片描述

那么这里开始解决问题,首先使用双指针来寻找从哪个元素开始从前往后复写。
定义两个变量prev = -1cur = 0,那么继续向后循环下面的步骤

  1. 访问cur位置的元素
  2. 通过cur位置的元素判断prev移动一步(非零元素)还是两步(零)
  3. 判断prev是否到达数组的末尾
  4. 若prev未到达数组末尾,cur++,重复上面操作,到达末尾则结束

但是上面的操作还是存在漏洞,那就是并未解决可能会出现越界的问题。
出现prev越界的情况一定是最后一个复写的元素为零时,剩下的空间不足值,导致prev越界,那么我们这里做一个特殊判断,当越界时,cur--prev-=2,而数组最后一个元素赋值为0,那么这里就是解决从哪里开始复写和越界的问题了。

剩下的问题就很简单了,知道了从哪里开始从后往前开始复写,相信大家看完下面的代码就能理解了,下面还有一张关于越界和非越界情况的图解,希望能够对大家有所帮助。
在这里插入图片描述


编写代码

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int prev = -1, cur = 0;
        // 因为数组的末尾的位置是size-1
        // 而prev的位置只能是size-1(末尾)或是size的位置(越界)
        // 所以prev的位置不能超过size-1,否则prev则会变为为size和size+1

        // 由于size()的返回值是size_t
        // 与int比较时会发生类型提升
        // 导致-1 > 0,所以这里将size()强转为int进行比较
        while (prev < (int)arr.size() - 1)
        {
            if (arr[cur] != 0)
                prev++;
            else
                prev += 2;

            // 当prev到数组尾或越界时,cur不需要++
            if (prev < arr.size() - 1)
                cur++;
        }

        // 这里prev越界了,需要-=2
        // cur需要向前移动改变复写开始的位置
        if (prev == arr.size())
        {
            prev -= 2;
            cur--;
            arr[arr.size() - 1] = 0;
        }

        while (cur >= 0)
        {
            if (arr[cur] == 0)
            {
                arr[prev--] = 0;
                arr[prev--] = 0;
            }
            else
            {
                arr[prev--] = arr[cur];
            }
            cur--;
        }
    }
};

三、快乐数

题目描述
在这里插入图片描述


思路讲解

我以两个示例画个图来解决问题,大家可能会认为这个图会有点眼熟。
在这里插入图片描述
在这里插入图片描述

相信大家看到这个形状就会感到非常的熟悉,没错!这就是链表中学到过的判断链表是否带环,思路就是快慢双指针。首先有一个链表,下面是带环定义两个变量slow和fast,由于循环条件的问题,slow与fast不能相等,所以使slow与fast分别指向头部的元素和头部的元素的下一个,那么下面就是循环部分了,fast每一次走两步,slow每一次走一步,如果链表带环,那么fast与slow一定会相遇,那么相反,若fast走到尾部则说明链表中不带环。

一般我们看到这道题会会想到三种情况,但是由于题目传来的数字是int类型的,所以int数字最大的情况是2^31,也就是2147483647,而这道题中下一个数字是上一个数字每个数字的平方和,那么我们将数字再次放到为9999999999,那么下一个数最大为 9^2 * 10 = 810,那么就说明下一个数得到的范围是0~810,那么就可以得到这道题中这些数字是一点会有循环的,那么第三种情况是不存在的。
在这里插入图片描述

虽然说这里并没有真实的链表,但是这里还是可以复用上面的思想,定义两个变量slow和fast,由于循环条件的问题,slow与fast不能相等,所以使slow与fast分别赋值为第一个数字和第二个数字,fast每次变化两次,slow每次变化一次,由于本题一定会有循环的数字,那么这里我们判断当fast与slow相遇时,当前的数字和下一个数字是否相等,相等则符合条件,因为只有1变化后不变。


编写代码

class Solution {
public:
	// 得到n每一位的平方和
    int getSum(int n)
    {
        int sum = 0;
        while (n)
        {
            int ret = n % 10;
            sum += ret * ret;
            n /= 10;
        }
        return sum;
    }

    bool isHappy(int n) {
        int slow = n, fast = getSum(n);
        while (slow != fast)
        {
            slow = getSum(slow);
            fast = getSum(getSum(fast));
        }

        if (slow == getSum(slow))
            return true;
        else
            return false;
    }
};

四、 盛最多水的容器

题目描述
在这里插入图片描述


思路讲解
由图可知,存储水量的大小 (V)= 两根垂线中矮的(h) * 两个垂线的距离(l),那么我们这里的思路是定义两个变量left和right分别指向数组的头和尾,再定义一个变量MaxV用来记录最大储水量。我们可以发现一个规律,left和right向中间移动时,l一定减小,下面分下面两种情况:

  1. 两根垂线中高的向中间移动,由于矮的高度一定不变,若高的变得比原来更高,但是矮的已经确定,那么h也就确定了不变,并且由于l减小,那么V就会变小,若高的变得比矮的还矮,那么这里就是hl同时减小,那么V一定减小,总而言之,两根垂线中高的向中间移动,V一定变小。
  2. 两根垂线中矮的向中间移动,由于的高的高度一定不变,若矮的变的更矮,那么V就会变小,若矮的高度变高,那么V可能变大。

看完上面两种情况后,我们知道,两根垂线中高的向中间移动,V一定变小,两根垂线中矮的向中间移动,V不一定变小,所以这里定义一个变量MaxV记录最大的储水量,定义一个变量V记录每次储存水量的大小,每次记录完后两根垂线中矮的向中间移动,若V比MaxV大,将V赋值给MaxV,直到两根垂线相遇后结束,最后返回MaxV的值则完成本题 。


编写代码

class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0 , right = height.size()-1;
        int MaxV = 0 , V = 0;
        while(left < right)
        {
            if(height[left] > height[right])
            {
                V = height[right] * (right-left);
                right--;
            }
            else
            {
                V = height[left] * (right-left);
                left++;
            }
            MaxV = MaxV > V ? MaxV : V;
        }
        return MaxV;
    }
};

五、有效三角形的个数

题目描述
在这里插入图片描述


思路讲解:首先将数组排序一下变为升序,首先定义三个变量MaxToMini、left 和 right,首先将MaxToMini定位到数组的最右边边,left 和 right分别定位到 数组的最左边和 MaxToMini的左边,再定义一个count记录有效三角形的个数。

这里的思想是,若left 和 right 指向位置的数字加起来比 MaxToMini 指向位置的数字大,又 left 到 right 位置上的数字都比 left 位置上的数字大或相等,所以这一段上的数字一定能与 MaxToMini 和 right位置上的数字组成一个三角形,将 left 和 right 之间的数字的个数加到 count 中,再将right--从新开始判断。若 left 和 right 指向位置的数字加起来比 right指向位置的数字小,则将left向右移动,使left位置指向的数字增大,最终变为上面一种情况或是这一次的三个数字不能组成三角形。当left 与 right相遇,那么这次内循序结束,使MaxToMini向左移动,重新定位left和right,直到MaxToMini移动到最左边后完成外循环,最后返回count则完成本道题。

在这里插入图片描述


编写代码

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        // 首先将数组排为有序
        sort(nums.begin(),nums.end());

        int MaxToMini = nums.size()-1;
        int left = 0 , right = MaxToMini - 1;
        int count = 0;

        while(MaxToMini)
        {
            while(left < right)
            {
                if(nums[left] + nums[right] > nums[MaxToMini])
                {
                    count += (right-left);
                    right--;
                }
                else
                {
                    left++;
                }
            }

            MaxToMini--;
            right = MaxToMini-1;
            left = 0;
        }

        return count;
    }
};

六、查找总价格为目标值的两个商品

题目描述

在这里插入图片描述


思路讲解
首先将数组排序一下变为升序,定义两个变量 left 和 right ,分别定位在数组的最左边和最右边,若两个位置指向数字之和小于price,那么 left 向右移动,使两者之和变大,若两个位置指向数字之和大于price,那么 right 向左移动,使两者之和变小,若两个位置指向数字之和等于price,将这两个数字插入到vector中,最后返回vector完成本题。


编写代码

class Solution {
public:
    vector<int> twoSum(vector<int>& price, int target) {
        int left = 0 , right = price.size()-1;
        vector<int> ans;
        while(left < right)
        {
            if(price[left] + price[right] > target)
                right--;
            else if(price[left] + price[right] < target)
                left++;
            else
            {
                ans.push_back(price[left]);
                ans.push_back(price[right]);
                break;
            }
        }
        return ans;
    }
};

七、三数之和

题目描述
在这里插入图片描述


思路讲解
首先将数组排序一下变为升序,定义三个变量 MinToMaxi 、 left 和 right,分别定位到数组的最左边、MinToMaxi的右边和数组的最右边和,本题中不能存在相同的三元组若三个位置上的数字之和大于0,那么使right向左移动,并且移动时跳过与上一个数字相同元素,使三数之和变小,若三个位置上的数字之和小于0,使left向右移动,并且移动时跳过与上一个数字相同元素,使三数之和变大,若三个位置上的数字之和等于0,则将这三个数字放入vector中,为了去重,将这三个数字放到vector后,left 和 right同时向中间移动,并且在移动时需要跳过被放入三元组中相同的元素,直到left与right相遇后,本次内循环结束,MinToMaxi向右移动,并且为了去重,MinToMaxi也需要跳过相同的元素,移动后重新定位left和right,开始新一轮的内循环,重复上面的操作,直到MinToMaxi移动到最右边时,完成外循环,返回vector后完成本题。

本题还有一个小优化,由于 MinToMaxi 指向位置的数字是三个中最小的,若这个数字都大于0那么后面的循环中不可能出现三数之和为0的情况,可以直接结束外循环。

在这里插入图片描述


编写代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int MinToMaxi = 0;
        int left = MinToMaxi + 1, right = nums.size() - 1;
        int pos = 0;
        vector<vector<int>> ans;

        // 这里nums[MinToMaxi] <= 0算是一个小小的优化
        // 由于该数组是被排序过的,当三个数字中最小的
        // 也大于0,那么三数之和就不可能为0
        while (MinToMaxi < nums.size() && nums[MinToMaxi] <= 0)
        {
            while (left < right)
            {
                if (nums[left] + nums[right] > -nums[MinToMaxi])
                {
                    // 将相同元素全部略过
                    while (right > 1 && nums[right] == nums[right - 1])
                    {
                        right--;
                    }
                    // 移到下一个不相同的元素
                    right--;
                }
                else if (nums[left] + nums[right] < -nums[MinToMaxi])
                {
                    // 将相同元素全部略过
                    while (left < nums.size() - 1 && nums[left] == nums[left + 1])
                    {
                        left++;
                    }
                    // 移到下一个不相同的元素
                    left++;
                }
                else
                {
                    vector<int> tmp;
                    tmp.push_back(nums[MinToMaxi]);
                    tmp.push_back(nums[left]);
                    tmp.push_back(nums[right]);

                    ans.push_back(tmp);

                    // 这里防止right-1 < 0,出现越界的情况
                    while (right > 1 && nums[right] == nums[right - 1])
                    {
                        right--;
                    }
                    right--;

                    // 这里防止left + 1 >= nums.size() ,出现越界的情况
                    while (left < nums.size() - 1 && nums[left] == nums[left + 1])
                    {
                        left++;
                    }
                    left++;
                }
            }
            // 更新指向位置

            while (MinToMaxi < nums.size() - 1 && nums[MinToMaxi] == nums[MinToMaxi + 1])
            {
                MinToMaxi++;
            }
            MinToMaxi++;

            left = MinToMaxi + 1;
            right = nums.size() - 1;
        }
        return ans;
    }
};

八、四数之和

题目描述

在这里插入图片描述


思路讲解
本题思路与上面三数之和的思路基本类似,上面题中每次判断需要三个数,每次内循环中,只需要固定一个数,移动两个数 ,而本道题判断需要四个数,所以需要固定两个数,移动两个数。所以这里与上面题的思路相似,只需要在嵌套一层循环,再固定一个数,那么这题就不做详细的讲解了。


编写代码

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        int size = nums.size();
        vector<vector<int>> ans;
        int MinToMaxi1 = 0 , MinToMaxi2 = 1;
        int left = 2 , right = size-1;
        while(MinToMaxi1 < size-1)
        {
            while(MinToMaxi2 < size-1)
            {
                while(left < right)
                {
                    long long tmp = (long long)target - nums[MinToMaxi1] - nums[MinToMaxi2];
                    if(nums[left] + nums[right] > tmp)
                    {
                        while(right > 1 && nums[right] == nums[right-1])
                        {
                            right--;
                        }
                        right--;
                    }
                    else if(nums[left] + nums[right] < tmp)
                    {
                        while(left < size - 1 && nums[left] == nums[left+1])
                        {
                            left++;
                        }
                        left++;
                    }
                    else
                    {
                        vector<int> ret;
                        ret.push_back(nums[MinToMaxi1]);
                        ret.push_back(nums[MinToMaxi2]);
                        ret.push_back(nums[left]);
                        ret.push_back(nums[right]);

                        ans.push_back(ret);

                        while(right > 1 && nums[right] == nums[right-1])
                        {
                            right--;
                        }
                        right--;

                        while(left < size - 1 && nums[left] == nums[left+1])
                        {
                            left++;
                        }
                        left++;
                    }
                }
                while(MinToMaxi2 < size - 1 && nums[MinToMaxi2] == nums[MinToMaxi2+1])
                {
                    MinToMaxi2++;
                }
                MinToMaxi2++;

                left = MinToMaxi2 + 1;
                right = size - 1;
            }
            while(MinToMaxi1 < size - 1 && nums[MinToMaxi1] == nums[MinToMaxi1+1])
            {
                MinToMaxi1++;
            }
            MinToMaxi1++;

            MinToMaxi2 = MinToMaxi1 + 1;
            left = MinToMaxi2 + 1;
            right = size - 1;
        }
        return ans;
    }
};

结尾

如果有什么建议和疑问,或是有什么错误,大家可以在评论区中提出。
希望大家以后也能和我一起进步!!🌹🌹
如果这篇文章对你有用的话,希望大家给一个三连支持一下!!🌹🌹

在这里插入图片描述

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

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

相关文章

C++常用的特性-->day05

友元的拓展语法 声明一个类为另外一个类的友元时&#xff0c;不再需要使用class关键字&#xff0c;并且还可以使用类的别名&#xff08;使用 typedef 或者 using 定义&#xff09;。 #include <iostream> using namespace std;// 类声明 class Tom; // 定义别名 using …

Vue3 + Vite 构建组件库的整体流程

Vue3 Vite 构建组件库的流程 本文教你如何用 Vue Vite&#xff0c;一步一步构建一个组件库并发布到 npm 的整体流程 1. 通过 vite 命令创建一个基本的项目结构&#xff08;这里选用 vue ts 的项目&#xff09; npm create vitelatest2. 在项目中创建一个 lib 目录&#xf…

Ubuntu22.04.2 k8s部署

k8s介绍 简单介绍 通俗易懂的解释&#xff1a; Kubernetes&#xff08;也被称为 K8s&#xff09;就像是一个大管家&#xff0c;帮你管理你的云计算服务。想象一下&#xff0c;你有很多个小程序&#xff08;我们称之为“容器”&#xff09;&#xff0c;每个都在做不同的事情&…

UniApp的Vue3版本中H5配置代理的最佳方法

UniApp的Vue3版本中H5项目在本地开发时需要配置跨域请求调试 最开始在 manifest.json中配置 总是报404&#xff0c;无法通过代理请求远程的接口并返回404错误。 经过验证在项目根目录创建 vite.config.js文件 vite.config.js内容: // vite.config.js import {defineConfig }…

Android OpenGL ES详解——实例化

目录 一、实例化 1、背景 2、概念 实例化、实例数量 gl_InstanceID 应用举例 二、实例化数组 1、概念 2、应用举例 三、应用举例——小行星带 1、不使用实例化 2、使用实例化 四、总结 一、实例化 1、背景 假如你有一个有许多模型的场景&#xff0c;而这些模型的…

2024数维杯问题C:脉冲星定时噪声推断和大气时间信号的时间延迟推断的建模完整思路 模型 代码结果

&#xff08;Modeling of pulsar timing noise deduction and atmospheric time delay deduction of time signals&#xff09; 脉冲星是一种连续而稳定的快速旋转的中子星&#xff0c;为它们赢得了“宇宙的李温室”的绰号。脉冲星的空间观测对深空航天器的导航和时间标准的维…

Shell基础2

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团…

基于微信小程序的校园超市购物系统设计与实现,LW+源码+讲解

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本超市购物系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&a…

【golang-技巧】-线上死锁问题排查-by pprof

1.背景 由于目前项目使用 cgo golang 本地不能debug, 发生死锁问题&#xff0c;程序运行和期待不一致&#xff0c;通过日志排查可以大概率找到 阻塞范围&#xff0c;但是不能找到具体问题在哪里&#xff0c;同时服务器 通过k8s daemonset 部署没有更好的方式暴露端口 获取ppr…

【Visual Studio】设置文件目录

打开属性 输出目录&#xff1a;$(SolutionDir)bin\$(Platform)\$(Cinfiguration)\ 中间目录&#xff1a;$(SolutionDir)bin\intermediates\$(Platform)\$(Cinfiguration)\

智谱AI清影升级:引领AI视频进入音效新时代

前几天智谱推出了新清影,该版本支持4k、60帧超高清画质、任意尺寸&#xff0c;并且自带音效的10秒视频,让ai生视频告别了"哑巴时代"。 智谱AI视频腾空出世&#xff0c;可灵遭遇强劲挑战&#xff01;究竟谁是行业翘楚&#xff1f;(附测评案例)之前智谱出世那时体验了一…

Datawhale模型压缩技术Task2之模型剪枝

模型剪枝 模型剪枝介绍何为剪枝&#xff08;What is Pruning?&#xff09;剪枝类型非结构化剪枝结构化剪枝半结构化剪枝 剪枝范围局部剪枝全局剪枝 剪枝粒度细粒度剪枝基于模式的剪枝向量级剪枝内核级剪枝通道级剪枝 为何剪枝&#xff08;Why Pruning?&#xff09;剪枝标准&a…

雨晨 Fix 24H2 Windows 11 iot 企业版 ltsc 2024 极简 2合1 26100.2448

映像的详细信息: 雨晨 Fix 24H2 Windows 11 iot 企业版 ltsc 2024 极简 2合1 26100.2448 索引: 1 名称: Windows 11 IoT 企业版 LTSC 2024 极简V1 26100.2448 (传统legacy资源管理器) 描述: Windows 11 IoT 企业版 LTSC 2024 极简V1 26100.2448 By YCDISM v2025 2024-11-15 大…

【Qt聊天室】客户端实现总结

目录 1. 项目概述 2. 功能实现 2.1 主窗口设计 2.2 功能性窗口 2.3 主界面功能实现 2.4 聊天界面功能实现 2.5 个人信息功能开发 2.6 用户信息界面设置功能 2.7 单聊与群聊 2.8 登录窗口 2.9 消息功能 3. 核心设计逻辑 3.1 核心类 3.2 前后端交互与DataCenter 4…

3、.Net UI库:CSharpSkin - 开源项目研究文章

CSharpSkin(C# 皮肤)是一个基于C#语言开发的UI框架&#xff0c;它允许开发者使用C#和.NET技术栈来创建跨平台的桌面应用程序。CSharpSkin框架通常用于实现具有自定义外观和感觉的应用程序界面&#xff0c;它提供了一套丰富的控件和组件&#xff0c;以及灵活的样式和布局系统。 …

JUC包中常用类解析

目录 &#xff08;一&#xff09;Callable接口 &#xff08;1&#xff09;Callable与Runnable的区别 &#xff08;2&#xff09;Future接口 2.1Futrue接口中的方法 2.2FutureTask类 &#xff08;3&#xff09;Callable接口的使用 3.1借助FutureTask运行 3.2借助线程池运…

交友问题 | 动态规划

描述 如果有n个人&#xff0c;每个人都可以保持单身或与其他人结成一对。每个人只能找一个对象。求总共有多少种保持单身或结对的方式。用动态规划求解。 输入 输入第一行t表示测试用例的数量 对于每一个测试用例, 输入一个整数n表示人数1<n<18 输出 针对每个测试用…

【WPF】Prism库学习(一)

Prism介绍 1. Prism框架概述&#xff1a; Prism是一个用于构建松耦合、可维护和可测试的XAML应用程序的框架。它支持WPF、.NET MAUI、Uno Platform和Xamarin Forms等多个平台。对于每个平台&#xff0c;Prism都有单独的发布版本&#xff0c;并且它们在不同的时间线上独立开发。…

基于Java Springboot在线音乐试听交流网站

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据库&#xff…

# 第20章 Cortex-M4-触摸屏

第20章 Cortex-M4-触摸屏 20.1 触摸屏概述 20.1.1 常见的触摸屏分类 电阻式触摸屏、电容式触摸屏、红外式触摸屏、表面声波触摸屏 市场上用的最多的是电阻式触摸屏与电容式触摸屏。红外管式触摸屏多用于投影仪配套设备。 电阻式触摸屏构成&#xff1a;整个屏由均匀电阻构成…