利用哈希表优化算法,求出数组中最大无相邻重复数字子序列的长度。
例题:对于一段给定长度n的数组,求符合任意两个相邻元素都不相等的子序列最大长度
其中第一行输入数组长度,第二行输入一段整数,表示这个数组。
例:5
1 2 2 3 5。
一、朴素算法如何解决这个问题?
即利用i,和j,分别遍历数组,求出每个符合条件的子序列长度,再输出最大值。
不难发现,朴素算法的时间复杂度是O(n*2)。
int ans = 1;
int cnt = 1;//cnt 表示当前搜索的符合条件的序列长度。且cnt最小值为1(子序列长度最小为1)
for(int i = 0;i < n-1;i++)
for(int j = i+1;j <= n-1;j++){
if(a[i] != a[j]){
cnt ++;
ans = max(cnt,ans)
}
if(a[i] == a[j]){//如果相邻元素相同,则初始化,即令cnt = 1;
cnt = 1;
}
}
cout << ans << endl;
二、利用哈希表优化。
核心步骤:通过只遍历一遍数组,利用O(n)的复杂度,达到寻找并存储符合条件的子序列,并输出子序列长度最大值。
int find(int a[]){
int ans = 1;
h[1] = a[0];//在h[1]处新建一个链表,h[1]指向a[0]。
for(int i = 1;i <= n-1;i++){
if(a[i]!=a[i-1]){//对于当前子序列,如果相邻元素不相等,则操作对应链表。
e[idx] = a[i];
ne[idx] = h[siz];
h[siz] = idx++;
cnt ++;
ans = max(ans,cnt);
}
if(a[i]==a[i-1]){//相邻元素相等,则新开链表,并继续搜索a数组剩余元素。
cnt = 1;
siz ++;
}
}
return ans;
}
如此,我们便能将O(n*2)的朴素算法利用哈希优化为O(n)的算法。
总结
全部代码:
#include <iostream>
using namespace std;
const int N = 100010;
int a[N],h[N],ne[N],e[N];
int n,idx,siz = 1,cnt = 1;
int max(int a,int b){
if(a >= b)return a;
else return b;
}
int find(int a[]){
int ans = 1;
h[1] = a[0];
for(int i = 1;i <= n-1;i++){
if(a[i]!=a[i-1]){
e[idx] = a[i];
ne[idx] = h[siz];
h[siz] = idx++;
cnt ++;
ans = max(ans,cnt);
}
if(a[i]==a[i-1]){
cnt = 1;
siz ++;
}
}
return ans;
}
int main(){
cin.tie(0);
ios::sync_with_stdio(false);
cin >> n;
int max1 = cnt;
for(int i = 0;i < n;i++)cin >> a[i];
cout << find(a);
return 0;
}