算法学习入门---双指针(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;
}
相关推荐
进击的横打7 分钟前
【车载开发系列】安全算法与安全访问
算法·安全·车载系统
努力学算法的蒟蒻8 分钟前
day59(1.18)——leetcode面试经典150
算法·leetcode·职场和发展
666HZ66610 分钟前
数据结构3.0 栈、队列和数组
开发语言·数据结构·算法
知乎的哥廷根数学学派10 分钟前
基于物理引导和不确定性量化的轻量化神经网络机械退化预测算法(Python)
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习
程序员-King.12 分钟前
day146—递归—验证二叉搜索树(LeetCode-98)
算法·leetcode·二叉树·递归
永远都不秃头的程序员(互关)13 分钟前
【K-Means深度探索(五)】不止欧氏距离:K-Means中距离度量那些事儿
算法·机器学习·kmeans
tobias.b16 分钟前
408真题解析-2009-41-数据结构-最短路径
数据结构·算法·计算机考研·408考研·408真题解析
王老师青少年编程17 分钟前
2024年9月GESP真题及题解(C++七级): 矩阵移动
c++·算法·题解·真题·gesp·七级·矩阵移动
txinyu的博客21 分钟前
连接池问题
服务器·网络·c++
棒棒的皮皮24 分钟前
【深度学习】YOLO 进阶提升之算法改进(新型骨干网络 / 特征融合方法 / 损失函数设计)
深度学习·算法·yolo·计算机视觉