intmain(){ char c[100]; fgets(c,100,stdin); int n = strlen(c); for (int i = 0;i < n;i++){ int j = i; while (j < n && c[j] != ' ') j++; for (int k = i;k < j;k++) printf("%c",c[k]); puts(""); /* 这道题的具体逻辑:第一次 i指向第一个单词的首字母, j结束时指向第一个空格,输出第一个单词并换行,令 i=j,i指向第一个空格 下一次最外层的循环中,i++,i指向第二个单词的首字母,同上操作 */ i = j;// 外层循环中有i++,在双指针算法中特别注意! } return0; } /*Hello world This is c Hello world This is c*/
例题:799. 最长连续不重复子序列(模板题)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。
输入格式 第一行包含整数 n。 第二行包含 n 个整数(均在 0∼10^5 范围内),表示整数序列。
输出格式 共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。
数据范围 1≤n≤10^5 输入样例: 5 12235 输出样例: 3
首先,我们想一下朴素做法怎么解决,再去考虑双指针算法来优化就比较好想。
朴素做法: 假设 i 是终点,j 是起点,先枚举终点 i,再枚举起点 j。
1 2 3 4 5 6 7
// 朴素做法: O(n^2) for (int i = 0;i < n;i++) for (int j = 0;j <= i;j++){ if (check(j,i)){ res = max(res,i-j+1); } }
本质: j 尽可能与 i 的距离变大,并保证没有重复数字。
双指针优化:朴素做法的指针j每次都从0开始,没有必要。
当 i 向右移动时,j 指针不会回退,只能不动或者向右移动 (如果 j 需要向右移动,则表示表示出现重复数字了,此时只需要把 j 向右移动,直到 i 和 j 之前没有重复数字为止)。即:保持一定的单调性。
1 2 3 4
// 双指针算法: O(n) for (int i = 0,j = 0;i < n;i++) while (j <= i && check(j,i)) j++; res = max(res,i-j+1);