双指针算法
1.按行输出单词
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char str[1000];
gets(str);
int n = strlen(str);
for(int i = 0; i < n; i ++ )
{
int j = i;
while(j < n && str[j] != ' ') j ++ ;
//这道题目的具体逻辑
for(int k = i; k < j; k ++ ) cout << str[k];
cout << endl;
i = j;
}
return 0;
}
2.最长连续不重复子序列
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int a[N],s[N];
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ ) cin >> a[i];
int res = 0;
for (int i = 0, j = 0; i < n; i ++ )
{
s[a[i]] ++ ;
while (s[a[i]] > 1)
{
s[a[j]] -- ;
j ++ ;
}
res = max(res, i - j + 1);
}
cout << res << endl;
return 0;
}
离散化
//区间和
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 300010;//把出现的点都保存起来,最多300000个(n次坐标插入,m次查询,n+2m个)
int n, m;
int a[N], s[N];
vector<int> alls;//存储所有待离散化的值
typedef pair<int, int> PII;
vector<PII> add, query;
int find(int x)//映射关系,通过二分将原数组坐标映射到合适的新坐标,新数组坐标是原数组按下标从小到大排列
{
int l = 0, r = alls.size() - 1;
while (l < r)
{
int mid = (l + r) >> 1;
if(alls[mid] >= x) r = mid;
else l = mid + 1;
}
return r + 1;//映射后的数组下标从1开始:1,2,3,4...(不加1的话,映射到0,1,2,3...)
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i ++ )
{
int x, c;
cin >> x >> c;
add.push_back({x, c});//记录原数组x的位置需要加c
alls.push_back(x);//统计总共需要多少数组,将出现过的下标储存到alls中
}
for (int i = 0; i < m; i ++ )
{
int l, r;
cin >> l >> r;
query.push_back({l,r});//记录需要查询的区间[l, r]
alls.push_back(l);//将出现过的下标储存到alls中,为了统计总共需要多少数组
alls.push_back(r);//将出现过的下表储存到alls中,为了统计总共需要多少数组
}
//去重
sort(alls.begin(), alls.end());//对alls容器内元素排序
alls.erase(unique(alls.begin(), alls.end()), alls.end());//对alls容器内元素去重
//处理插入,根据题目要求将数轴上坐标加相应的数字
for (auto item : add)//循环条件是add的元素个数大于0。遍历add这个容器
{
int x = find(item.first);//item.first访问的是pair型变量add的第一项。将原数组的下标映射到离散化数组
a[x] += item.second;将原数组的值按下标赋给离散化数组
}
//预处理,前缀和
for (int i =1; i <= alls.size(); i ++ )
{
s[i] = s[i-1] + a[i];//计算离散化数组的前缀和
}
//处理询问
for (auto item : query)
{
int l = find(item.first), r = find(item.second);
cout << s[r] - s[l - 1] << endl;
}
return 0;
}
区间合并
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> PII;
int n;
vector<PII> segs;
void merge(vector<PII> &segs)//使用引用可以将原数组传入函数,不用复制一份,节省时间
{
vector<PII> res;
sort(segs.begin(), segs.end());
int st = -2e9, ed = -2e9;//设为极限左端点,这样任意给一个区间都可以进行区间操作,初始值要小于-1e9
for(auto seg : segs)
{
if(ed < seg.first)//当前维护区间与枚举的区间没有交集,即没有公共部分
{
if (st != -2e9) res.push_back({st, ed});//防止初始的st和ed,也就是st=-2e9 ed=-2e9被记录下来
st = seg.first;
ed = seg.second;
}
else//区间有公共部分
{
ed = max(ed, seg.second);
}
}
//将最后一个区间加入
if(st != -2e9)//防止输入的是空区间,即当n=0时不进行最后一个区间的记录
{
res.push_back({st, ed});
}
segs = res;
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ )
{
int l, r;
cin >> l >> r;
segs.push_back({l,r});
}
merge(segs);//区间和并
cout << segs.size() << endl;
return 0;
}