acw-4376.拍照2

题目链接https://www.acwing.com/problem/content/4370/

方法一 —— 反向比较(双指针)

分析

从后往前比较

想要求最小操作次数,那么每个数最多只能移动一次,因为一个数如果移动了两次,肯定也会影响其他的数,导致重复操作,竟然如此,我们就来求哪几个数需要移动就好了!需要移动的数的个数就是我们的最小操作数。

示例数据1:

一开始我们的指针都指向最后一个元素
5 4 3 2 1
        👆
1 2 3 4 5
        👆
我们移动a中指针找到与b指针相对应的奶牛
5 4 3 2 1
👆
1 2 3 4 5
        👆  
此时可以看出,在这头奶牛后一共有四头奶牛需要移动,所以答案就是 4

示例数据2:

5 1 3 2 4
    👆
4 5 2 1 3
        👆
可以看出,2、4是在奶牛3前面的,所以需要移动两次,同时标记这两个元素
5 1 3 2 4
  👆
4 5 2 1 3
      👆
两个指针都移动一次,发现所指奶牛一样,表示1、3奶牛之间不需要移动
5 1 3 2 4
👆
4 5 2 1 3
    👆
此时b指针指向2,a指针指向5,但2已经被标记过,所以2和5之间的奶牛不需要移动
5 1 3 2 4
👆
4 5 2 1 3
  👆
此时两指针指向的奶牛相同,不进行操作
所以最终的答案为 2

由示例可知:

当两个指针指向的牛不相同时,a指针向前移动,并对前面的奶牛进行标记,直至和b指针指向的奶牛一样,此时a,b指针都往前移动

如果b指针指向的牛没被标记过,继续比较,被标记过则b指针往前移动,直至指向没被标记的奶牛

代码:

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=100010;
int a[N];
int b[N];
bool st[N];	//标记奶牛是否移动过 
int n;

//双指针算法 -- 反向思维
// 
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	
	int res=0;
	for(int i=n,j=n;i&&j;i--,j--)
	{	
		//如果当前b指针指向的奶牛被标记过,直接跳过它,去找下一头牛 
		while(st[b[j]]) j--;
		//当两头奶牛的标号相同且没有被标记过时,可以进行操作了 
		while(a[i]!=b[j])
		{
			st[a[i]]=1;
			res++;
			i--;
		}
	}
	
	cout<<res<<endl;
	return 0;
	
}

方法二 —— 正向比较(双指针)

分析

从前往后比较

和反向比较差不多,只不过移动的是b指针,即当b指针指向的和a指针指向的不一样时,说明a中编号为b[j]的奶牛必定要移动,那么标记编号为b[j]的奶牛,b指针向后寻找,a指针指向第一个没被标记过的奶牛

代码:

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=100010;
int a[N];
int b[N];
bool st[N];	//标记奶牛是否移动过 
int n;

//双指针 -- 正向思维
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	
	int res=0,i=1;		//i指向a中的奶牛 
	for(int j=1;j<=n;j++)
	{
		//指向a中第一头未被标记的牛 
		while(st[a[i]]&&i<=n) i++;
		//如果指向的两头奶牛不一样,操作数++ 
		if(a[i]!=b[j]) res++;
		//标记b[j] 
		st[b[j]]=1;
	}

	cout<<res<<endl;
	return 0;	
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值