【双指针算法】最长连续不重复子序列 数组元素目标和 判断子序列

最长连续不重复子序列

2021.11.15

原题链接

活动 - AcWing系统讲解常用算法与数据结构,给出相应代码模板,并会布置、讲解相应的基础算法题目。https://www.acwing.com/problem/content/801/双指针的两种情形:

for(i=0,j=0;i<n;i++)
{
while(j<i&&check(i,j))j++;
check为判断性质条件
}

 核心思想是

for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
O(n*n)

 将时间复杂度优化到O(n)

例题

输入 abc def hij 这样含空格的字符,输出字符每遇到一个空格,换行。

int main()
{
	string str;
	cin >> str;
	for (int i = 0; i<str.size(); i++)
	{
		int j = i;
		while (j <str.size()&& str[j] != ' ')j++;
		for (int k = i; k < j; k++)cout << str[k];
		cout << endl;
		i = j;
	}
}

原题模板

暴力做法
for(int i=0;i<n;i++)
for(int j=0;j<=i;j++)
if(check(j,i))
res=max(res,j-i+1);

双指针算法
for(int i=0,j=0;i<n;i++)
{
while(j<=i&&check(j,i))j++;
res=max(res,j-i+1);
}

注释

读入数据为 1 2 2 3 5

首先i在1上则s[1]=1;

然后i在2上则s[2]=1;

此时res=2;

然后i在2上则s[2]=2;

此时重复,则更新j的位置,j不停往前移动,直到将重复的元素删除,保证s[a[i]]都等于1

这时候j停止移动,i继续前进,直到i走到最后一个位置,则可以输出res(最大连续不重复元素),时间复杂度为O(n)

代码段

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &a[i]);

    int res = 0;
    for (int i = 0, j = 0; i < n; i++)
    {
        s[a[i]] ++;
        while (j < i && s[a[i]] > 1) s[a[j++]] --;
        res = max(res, i - j + 1);
    }
    cout << res << endl;
    return 0;
}

数组元素的目标和

2021.11.16

原题链接

活动 - AcWing系统讲解常用算法与数据结构,给出相应代码模板,并会布置、讲解相应的基础算法题目。https://www.acwing.com/problem/content/802/

暴力算法

//暴力做法
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(a[i]+b[i]==x)
O(nm)

时间复杂度O(NM) 

双指针算法 

利用数组升序排序的单调性

假设

A 1 2 4 7

B 3 4 6 8 9

x 6 

一开始i=0,j=4

由于后面的a[i]>a[0]

而a[0]+b[4]>6,所以必然a[i]+b[4]>6 

所以j往前一个位置依旧a[0]+b[3]>6

直到a[0]+b[1]<6这时j=1;

i++;此时在进行如上的操作,最后找到 i=1,j=1满足

时间复杂度O(N+M)

代码段

int main()
{
    scanf("%d%d%d", &n, &m, &x);
    for (int i = 0; i < n; i++)scanf("%d", &a[i]);
    for (int i = 0; i < n; i++)scanf("%d", &b[i]);
    for (int i = 0, j = m - 1; i < n; i++)
    {
        while (j >= 0 && a[i] + b[i] > x)j--;
        if (a[i] + b[j] == x)
        {
            printf("%d %d\n", i, j);
            break;
        }
    }
}

判断子序列

2021.11.17

原题链接

2816. 判断子序列 - AcWing题库高质量的算法题库https://www.acwing.com/problem/content/2818/

解释

找到一种a[i]和b[j]的匹配模式,即a[i]=b[j],如果在b[j]中找到全部的a[i],则输出YES

时间复杂度O(n)

代码段

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++)scanf("%d", &a[i]);
    for (int i = 0; i < n; i++)scanf("%d", &b[i]);
    int i = 0, j = 0;
    while (i < n && j < m)
    {
        if (a[i] == b[j])i++;
        j++;
    }
    if (i == n)puts("YES");
    else puts("NO");
}

Guess you like

Origin blog.csdn.net/nathanqian123/article/details/121337781