当前位置: 首页 > news >正文

【算法300题】:双指针

双指针板块

925. 长按键入

leetcode链接

你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。

你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True。

思路

这道题目只要是末尾的边界条件比较恶心一点

class Solution {
public:bool isLongPressedName(string name, string typed) {int cur = 0;if(name[0] != typed[0]) return false;for(auto ch : name){if(ch == typed[cur]){// 匹配成功++cur;}else {// 匹配失败// 可能上一个字符多键入了auto prev_chr = typed[cur - 1];while(cur < typed.size() && typed[cur] == prev_chr) cur++;if(cur < typed.size() && typed[cur] == ch) {cur++;}else return false; }}// 找找还有没有词auto prev_chr = typed[cur - 1];while(cur < typed.size() && typed[cur] == prev_chr) cur++;if(cur < typed.size()) return false;return true;}
};

532. 数组中的 k-diff 数对

leetcode链接

给你一个整数数组 nums 和一个整数 k,请你在数组中找出 不同的 k-diff 数对,并返回不同的 k-diff 数对 的数目。

k-diff 数对定义为一个整数对 (nums[i], nums[j]) ,并满足下述全部条件:

0 <= i, j < nums.length
i != j
|nums[i] - nums[j]| == k
注意,|val| 表示 val 的绝对值。

示例 1:

输入:nums = [3, 1, 4, 1, 5], k = 2
输出:2
解释:数组中有两个 2-diff 数对, (1, 3) 和 (3, 5)。
尽管数组中有两个 1 ,但我们只应返回不同的数对的数量。
示例 2:

输入:nums = [1, 2, 3, 4, 5], k = 1
输出:4
解释:数组中有四个 1-diff 数对, (1, 2), (2, 3), (3, 4) 和 (4, 5) 。
示例 3:

输入:nums = [1, 3, 1, 5, 4], k = 0
输出:1
解释:数组中只有一个 0-diff 数对,(1, 1)

思路

第一版的思路就是直接查找, 但是k == 0单独讨论一下, 不然确实不好处理

class Solution {
public:int getPrevDiffNum(vector<int>& num,int pos){int res = pos - 1;while(res >= 0 && num[res] == num[pos]) res--;return res;// -1}int getNextDiffNum(vector<int>& num,int pos){int res = pos + 1;while(res < num.size() && num[res] == num[pos]) res++;return res;}int findPairs(vector<int>& nums, int k) {// 暴力算法// 单独处理k == 0sort(nums.begin(), nums.end());if(k == 0){int count = 0;for(int i = 0;i < nums.size();i = getNextDiffNum(nums,i))if(i + 1 < nums.size() && nums[i] == nums[i + 1]) count++;return count;}int n = nums.size();int count = 0;for(int i = 0;i < n;i = getNextDiffNum(nums,i)){auto prev_diff_pos = i;while(prev_diff_pos != -1){if(nums[i] - nums[prev_diff_pos] >= k) break;prev_diff_pos = getPrevDiffNum(nums, prev_diff_pos);}if(prev_diff_pos != -1 && nums[i] - nums[prev_diff_pos] == k) {count++;}}return count;}
};

思路

我们在查找的时候可以使用二分进行速度的优化。确实快了一些

class Solution {
public:int getPrevDiffNum(vector<int>& num,int pos){int res = pos - 1;while(res >= 0 && num[res] == num[pos]) res--;return res;// -1}int getNextDiffNum(vector<int>& num,int pos){int res = pos + 1;while(res < num.size() && num[res] == num[pos]) res++;return res;}int findPairs(vector<int>& nums, int k) {// 暴力算法// 单独处理k == 0sort(nums.begin(), nums.end());if(k == 0){int count = 0;for(int i = 0;i < nums.size();i = getNextDiffNum(nums,i))if(i + 1 < nums.size() && nums[i] == nums[i + 1]) count++;return count;}// 如果k != 0, 首先进行去重// 通过二分查找进行优化之前的逻辑int count = 0;for(int i = getNextDiffNum(nums,0);i < nums.size();i = getNextDiffNum(nums,i)){int left = 0, right = i - 1;while(left < right){int mid = left + (right - left) / 2;if(nums[i] - nums[mid] > k) left = mid + 1;else right = mid;}if(nums[i] - nums[left] == k) count++;}return count;}
};

56. 合并区间

leetcode

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

class Cmp
{
public:// we must guarentee vector.size() == 2bool operator()(const vector<int>& l,const vector<int>& r){return l[0] < r[0];}
};class Solution {
public:vector<vector<int>> merge(vector<vector<int>>& intervals) {vector<vector<int>> ret;std::sort(intervals.begin(),intervals.end(),Cmp());int prev_end = intervals[0][0];int prev_begin = intervals[0][0];intervals.push_back({INT32_MAX,INT32_MAX});for(auto& area : intervals){int begin = area[0], end = area[1];if(prev_end < begin){// 更新区间ret.push_back({prev_begin,prev_end});prev_begin = begin, prev_end = end;}else if(begin <= prev_end){// 出现交叉// 合并prev_end = std::max(prev_end,end);}}    return ret;}
};

75. 颜色分类

leetcode

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

必须在不使用库内置的 sort 函数的情况下解决这个问题。

示例 1:

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
示例 2:

输入:nums = [2,0,1]
输出:[0,1,2]

class Solution {
public: // 通过快排void sortColors(vector<int>& nums) {int left = -1, right = nums.size();int cur = 0;while(cur < right){if(nums[cur] == 0) std::swap(nums[cur++], nums[++left]);else if(nums[cur] == 1) cur++;else std::swap(nums[cur], nums[--right]);}    }
};

80. 删除有序数组中的重复项 II

leetcode

给定一个二进制数组 nums , 计算其中最大连续 1 的个数。

示例 1:

输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.
示例 2:

输入:nums = [1,0,1,1,0,1]
输出:2

提示:

1 <= nums.length <= 105
nums[i] 不是 0 就是 1.

class Solution {
public:int removeDuplicates(vector<int>& nums) {// 很简单的双指针的算法// count表示当前位置前面需要删除的个数int symbol = INT32_MAX;int symbol_count = 0;int offset = 0;for(int i = 0;i < nums.size();i++){if(nums[i] == symbol) {symbol_count++;if(symbol_count > 2)offset++;else{nums[i - offset] = nums[i]; }      }else {symbol = nums[i];symbol_count = 1;nums[i - offset] = nums[i];}}auto res = nums.size() - offset;nums.resize(res);return res;}
};

485. 最大连续 1 的个数

leetcode

给定一个二进制数组 nums , 计算其中最大连续 1 的个数。

示例 1:

输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.
示例 2:

输入:nums = [1,0,1,1,0,1]
输出:2

class Solution {
public:int findMaxConsecutiveOnes(vector<int>& nums) {int res = 0;int count = 0;for(auto i : nums) {if(i == 0){count = 0;}else {count++;res = std::max(res,count);}}    return res;}
};

524. 通过删除字母匹配到字典里最长单词

给你一个字符串 s 和一个字符串数组 dictionary ,找出并返回 dictionary 中最长的字符串,该字符串可以通过删除 s 中的某些字符得到。

如果答案不止一个,返回长度最长且字母序最小的字符串。如果答案不存在,则返回空字符串。

示例 1:

输入:s = “abpcplea”, dictionary = [“ale”,“apple”,“monkey”,“plea”]
输出:“apple”
示例 2:

输入:s = “abpcplea”, dictionary = [“a”,“b”,“c”]
输出:“a”

class Solution {
public:Solution() : _hash(26){}void initHashTable(const std::string& str){for(int i = 0;i < str.size();i++)_hash[str[i] - 'a'].push_back(i);}bool isFitChildString(const std::string& src){int cur = -1; for(auto ch : src){// 判断ch是否在(cur, end]中存在, 若存在找到最近的一个// 通过二分查找进行优化auto& posSet = _hash[ch - 'a'];if(posSet.empty()) return false;else{int left = 0, right = posSet.size() - 1;while(left < right){int mid = left + (right - left) / 2;if(posSet[mid] <= cur) left = mid + 1;else right = mid;}if(posSet[left] <= cur) return false;else cur = posSet[left];}}return true;}// 这道题目的本质就是判断dictionary中是否存在s的子序列, 对于大量判断, 通过hash来解决string findLongestWord(string s, vector<string>& dictionary) {initHashTable(s);string res;for(auto& dict : dictionary){if(isFitChildString(dict)){if(dict.size() > res.size()) res = dict;else if(dict.size() == res.size() && dict < res) res = dict;}}return res; }
// 通过hash + 二分进行优化private:vector<vector<int>> _hash;
};

986. 区间列表的交集

leetcode

给定两个由一些 闭区间 组成的列表,firstList 和 secondList ,其中 firstList[i] = [starti, endi] 而 secondList[j] = [startj, endj] 。每个区间列表都是成对 不相交 的,并且 已经排序 。

返回这 两个区间列表的交集 。

形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a <= x <= b 。

两个闭区间的 交集 是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3] 。

示例 1:

输入:firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]]
输出:[[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]
示例 2:

输入:firstList = [[1,3],[5,9]], secondList = []
输出:[]
示例 3:

输入:firstList = [], secondList = [[4,8],[10,12]]
输出:[]
示例 4:

输入:firstList = [[1,7]], secondList = [[3,10]]
输出:[[3,7]]

class Solution {
public:struct InterArea{InterArea(int left = -1,int right = -1) : _left(left), _right(right){}operator bool(){return _left != -1;} int _left;int _right;};// 判断两个区间是否存在公共部分InterArea isHasInterSection(vector<int>& l, vector<int>& r){if(l[0] > r[1] || l[1] < r[0]) return {-1, -1 };else return InterArea((int)std::max(l[0],r[0]), (int)std::min(l[1], r[1]));}vector<vector<int>> intervalIntersection(vector<vector<int>>& firstList, vector<vector<int>>& secondList) {vector<vector<int>> res;int start = 0;for(auto& List : secondList){while(start < firstList.size() && firstList[start][1] < List[0]) start++;auto cur = start;// 计算区间while(cur < firstList.size() && firstList[cur][0] <= List[1]){auto inter = isHasInterSection(firstList[cur], List);res.push_back({inter._left, inter._right});cur++;}}return res;}
};
http://www.lryc.cn/news/594534.html

相关文章:

  • c#转python第四天:生态系统与常用库
  • XSS的介绍
  • Linux主机 ->多机器登录
  • 从零到精通:用DataBinding解锁MVVM的开发魔法
  • 【JS逆向基础】数据库之MongoDB
  • Django接口自动化平台实现(四)
  • SpringBoot的配置文件
  • 测试学习之——Pytest Day4
  • WPF学习笔记(28)Interaction.Triggers的意义与使用方式
  • 人工智能之数学基础:随机实验、样本空间、随机事件
  • 均值漂移累积监测算法(MDAM):原理、命名、用途及实现
  • 爬虫实战案例(两个)
  • 【Lua】大G表
  • Linux 基本指令详解
  • 【论文研读】SlowFast Networks for Video Recognition
  • 大语言模型调用方式与函数调用
  • 从磁记录到数据中心:磁盘原理与服务器架构的完整技术链路
  • CVE-2022-41128
  • 六边形滚动机器人cad【7张】三维图+设计书明说
  • 从零搭建智能搜索代理:LangGraph + 实时搜索 + PDF导出完整项目实战
  • 【超越VGGT】π3-利用置换等变方法去除3r系列的归纳偏置
  • TypeScript 中替代 Interface 的方案
  • 一文速通《二次型》
  • UE5多人MOBA+GAS 26、为角色添加每秒回血回蓝(番外:添加到UI上)
  • 图的表示法以及实现
  • zabbix服务器告警处理
  • 【windows 终端美化】Windows terminal + oh-my-posh 来美化命令行终端
  • C++ 桶排序、基数排序、堆排序
  • Beamer-LaTeX学习(教程批注版)【6】
  • selenium4 web自动化测试