算法学习入门---双指针(C++)

目录

1.洛谷------UVA11572唯一的雪花

2.洛谷------逛画展

3.牛客网------字符串

4.牛客网------丢手绢


1.洛谷------UVA11572唯一的雪花

解题思路:hash表+滑动窗口

  • hash表可以用一个int数组来模拟
  • 滑动窗口即"同向双指针",具体看笔者的leetcode滑动窗口文章
  • 题目最后的cout需要加上换行符(卡了笔者10分钟的地方)

代码:

cpp 复制代码
#include<iostream>
#include<vector>
using namespace std;

int for_solution(int n, vector<int>& snowflakes)
{
    //双指针的运用
    vector<int> flag(n,0); //simulate hash array 
    int count = 0,max = -1;
    for(int left=0,right=0;right<=n-1;right++)
    {
         //进窗口
        int in = snowflakes[right]; 
		count++;
		flag[in]++;	
		//判断是否需要出窗口 
        while(flag[in]>1) 
        {
        	//开始出窗口 
        	int out = snowflakes[left++];
        	count--;
        	flag[out]--;
		}
		//每次进出完窗口,判断一下是否为最优解 
		if(count>max) max = count;
	}
    return max; 
}

int main()
{
    int T;
    cin>>T;
    for(int i=1;i<=T;i++)
    {
        int n;
        cin>>n;
        vector<int> snowflakes(n,0);
        for(int j=0;j<=n-1;j++) cin>>snowflakes[j];
        int ret = for_solution(n,snowflakes);
        cout<<ret<<endl;
    }
    return 0;
}

2.洛谷------逛画展

滑动窗口+hash表+count变量统计有效字符个数+数组下标从1开始(为了和题设重合)

注:INT_MAX 在 <climits> 头文件中

代码:

cpp 复制代码
#include<iostream>
#include<vector>
#include<climits>
using namespace std;

int main()
{
	int m,n;
	cin>>n>>m;
	vector<int> paintings(n+1,0);
	for(int i=1;i<=n;i++) cin>>paintings[i];
	int min = INT_MAX;
	int left_min=0,right_min=0;
	vector<int> hash(m+1,0);
	for(int left=1,right=1,count=0;right<=n;right++)
	{
		//进窗口+有效字符添加判断
		 int in = paintings[right];
		 if(!hash[in]) count++;
		 hash[in]++;
		//出窗口判断,count不为m时不可能作为答案,所以循环条件为 count == m 
		 while(count==m)
		 {
		 	//count为m时开始统计结果,此时不断出窗口,每次出窗口前更新一次结果
			if(right-left+1<min)
			{
				min = right-left+1;
				left_min = left;
				right_min = right;	
			} 
			//出窗口+有效字符删除判断 
			int out = paintings[left++];
			if(hash[out]==1) count--;
			hash[out]--; 
		 }
	} 
	cout<<left_min<<" "<<right_min<<endl;
	return 0;
}

3.牛客网------字符串

滑动窗口+hash表+表中字符逐一确认

代码:

cpp 复制代码
#include<iostream>
#include<string>
#include<vector>
#include<stdbool.h>
#include<climits>
using namespace std;
bool check(vector<int>& hash)
{
	//逐一判断
	for(int i=0;i<=25;i++)
		if(!hash[i]) return false;
	return true;
}

int main()
{
	string my_str;
	cin>>my_str;
	vector<int> hash(26,0);
	int min=INT_MAX;
	for(int left=0,right=0;right<=my_str.size()-1;right++)
	{
		//进窗口
		char in = my_str[right];
		hash[in-'a']++;
		while(check(hash))
		{
			//更新结果 
			if(right-left+1<min) min = right-left+1;
			//出窗口 
			char out = my_str[left++];
			hash[out-'a']--;
		}
	}
	cout<<min;
	return 0;
}

4.牛客网------丢手绢

如下图所示,n个小朋友围成一个圈,相邻小朋友之间距离不定,现求两个小朋友之间最远距离(可以是相邻也可以是非相邻)

如下图1所示,从1到2共有顺时针、逆时针两种方式;顺时针距离为1,逆时针距离为5,因此距离为1;因此每个同学之间需要计算顺时针、逆时针两种情况,并选择其中更短的一种情况

**重点:**此时我们可以把所有同学的距离相和,得到一个结果sum,统计结果加到 k 变量中;如下图2所示,当 k < sum / 2 时,得到的结果都是逆时针距离大于顺时针距离(此时逆时针距离 >= sum / 2 ),统计顺时针距离 k 为结果;当 k >= sum / 2 时,得到的结果都是逆时针距离小于顺时针距离,统计逆时针距离 sum - k 为结果


通过图2,我们也不难看出left、right移动对结果的单调性;left移动时k就减小,right移动时k就增大,k减小时right回到left位置就没有必要了,所以可以通过滑动窗口(同向双指针)来解决这道题

  • k < sum / 2 -> 进窗口 + 统计顺时针距离 k
  • k >= sum / 2 -> 出窗口 + 统计逆时针距离 sum - k
  • k >= sum / 2 容易出现精度问题,因此换成 2k >= sum
  • 出窗口要在统计顺时针距离 k 前,要不然无法保证统计顺时针距离时 k < sum / 2
  • 统计逆时针距离 sum - k 要在出窗口前,要不然会有情况(刚刚好达成进入循环时的情况)不被统计进结果

图1

图2

代码:

cpp 复制代码
#include<iostream>
#include<vector>
using namespace std;

int main()
{
	int num,sum=0,max = -1;
	cin>>num;
	vector<int> friends(num+1,0);
	for(int i=1;i<=num;i++) 
	{
		int in;
		cin>>in;
		sum+=in;
		friends[i] = in;	
	}
	//准备工作
	for(int left=1,right=1,k=0;right<=num;right++)
	{
		//进窗口
		k+=friends[right];
		//出窗口+统计逆时针结果
		while(2*k>=sum)
		{
			//统计逆时针结果
			if((sum-k)>max) max = sum - k;	
			//出窗口
			k-=friends[left++]; 
		} 
		//统计顺时针结果
		if(k>max) max = k; 
	}
	cout<<max;
	return 0;
}
相关推荐
Maple_land4 小时前
常见Linux环境变量深度解析
linux·运维·服务器·c++·centos
Larry_Yanan4 小时前
QML学习笔记(四十四)QML与C++交互:对QML对象设置objectName
开发语言·c++·笔记·qt·学习·ui·交互
Want5954 小时前
C/C++大雪纷飞①
c语言·开发语言·c++
Shilong Wang4 小时前
MLE, MAP, Full Bayes
人工智能·算法·机器学习
Theodore_10224 小时前
机器学习(6)特征工程与多项式回归
深度学习·算法·机器学习·数据分析·多项式回归
知花实央l4 小时前
【算法与数据结构】拓扑排序实战(栈+邻接表+环判断,附可运行代码)
数据结构·算法
Mr_WangAndy4 小时前
C++设计模式_行为型模式_策略模式Strategy
c++·设计模式·策略模式·依赖倒置原则
lingling0094 小时前
机械臂动作捕捉系统选型指南:从需求到方案,NOKOV 度量光学动捕成优选
人工智能·算法
吃着火锅x唱着歌5 小时前
LeetCode 410.分割数组的最大值
数据结构·算法·leetcode