1 条题解
-
1
使用双指针是降低算法复杂度的一个有效途径,有些问题的暴力解法时间复杂度是O(n^2),但使 用双指针可以大幅度降低算法复杂度。如果面试者能将求解过程从暴力法优化到双指针,说明面试者的基础知识、代码能力、逻辑思维都是十分扎实的。 同贪心算法一样,双指针的难点在于自己想不出、别人的理解不了、正确性难以证明。
核心思路
- 遍历数组a中的每一个元素a[i], 对于每一i,找到j使得双指针[j, i]维护的是以a[i]结尾的最长连续不重复子序列,长度为i - j + 1, 将这一长度与r的较大者更新给r。
- 对于每一个i,如何确定j的位置:由于[j, i - 1]是前一步得到的最长连续不重复子序列,所以如果[j, i]中有重复元素,一定是a[i],因此右移j直到a[i]不重复为止(由于[j, i - 1]已经是前一步的最优解,此时j只可能右移以剔除重复元素a[i],不可能左移增加元素,因此,j具有“单调性”、本题可用双指针降低复杂度)。
- 用数组s记录子序列a[j ~ i]中各元素出现次数,遍历过程中对于每一个i有四步操作:cin元素a[i] -> 将a[i]出现次数s[a[i]]加1 -> 若a[i]重复则右移j(s[a[j]]要减1) -> 确定j及更新当前长度i - j + 1给r。
# include <iostream> using namespace std; #define int long long const int N = 1e5 + 10,M = 1e7 + 10; int a[N], s[M]; signed main() { int n, r = 0; cin >> n; for (int i = 0, j = 0; i < n; ++ i) { cin >> a[i]; ++ s[a[i]]; while (s[a[i]] > 1) -- s[a[j++]]; // 先减次数后右移 r = max(r, i - j + 1) ; } cout << r; return 0; }
信息
- ID
- 64
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- (无)
- 递交数
- 48
- 已通过
- 20
- 上传者