算法训练营题目回顾

题目:重编码
题目分析: 此题为典型哈夫曼编码问题,思路为出现次数少的用的01数长度相对长~ 也就是深度相对较深~出现次数多(可以为深度)尽量小,最后使得
sum(d*n..此为出现次数与深度的乘积总和) 最小. 。。因为此题仅需求出其长度 所以可以根据huffman树启示 直接求出sum;
注(此题邓老师还有一个巧妙地运用队列和栈的解法,在视频中待整理)

以下是依据优先级队列属性求sum最小值的解法

int getAnswer(n , vector m){
priority_queue pq;ll sum =0;
for(int i =0;i1){
ll new_elem =0;
for(int j=0;j<2;j++){
new_elem+=pq.top();
pq.pop();
}
pq.push(new_elem);
sum+=new_elem;
}
return sum;
}
//此方法巧妙之处就在于巧妙地运用huffman树的特性但却不需要具体实现huffman树的结构从而直接得到需要求得sum的最小值. 需要使用到每个叶子节点的深度但却并不是也并不需要先求出各个节点的深度然后再用深度乘上个数然后再求和,而是每每选最小的节点然后直接使其合并 合并得到的值加入总和,即每当一个分支(此分支根节点值为最小俩节点之一)的所有节点深度须+1 (即当前最小的俩节点合并)则加上分支根节点的值即可,



题目:数字盒子:(此题可为理解散列表实现做铺垫)
如果数据量不大可以直接用bool数组直接取代 以空间利用率替换时间利用率,当数据量比较大时采用去取模操作,而针对冲突问题可采用vector或者链表形式存值具体思路如下:

const int MAX=1000007
vector a[MAX];
int Hash(int x){
return  x%MAX;
}

ll getAnswer(int op,int x){

int h =Hash(x);
vector::iterator ptr = table[h].end();//返回向量尾指针   
    for(vector::iterator it =a[h].begin();it::iterator it =a[h].begin();it

等式:
题意 t组数据 n个变量 m个条件
输入 a b e ;其中a、b代表第a、b个变量 e 为0或1 0为不相等 1为相等;
最后输出 这组数据能否成立 YesNo;
首先我们考虑蛮力解法依次遍历
以数组ID[i]=i初始化;然后先根据相等的条件给ID数组依次遍历赋值 ,最后对不相等条件依次排查看 若出现相等条件则输出No;
大致代码如下:int cnt =1;
for(i =0;i<=n;++i){
ID[i]=i;

if(e[i]==1){
    swap(a[i],a[cnt]);
    swap(b[i],b[cnt]);
    swap(c[i],c[cnt]);

}
}
for(i =0;i

if(e[i]==1){
for(i=1;i<=n;i++)
if (id[i]==id[b[i]])id[i]=id[a[i]];
}
else{
// e=0
if(id[a[i]]==id[b[i]])return"No";
}

}
return "Yes";
上述算法为蛮力算法复杂度高达mn O(n^2);
蛮力算法为我们提供了大体思路:所以我们可以根据蛮力算法进行优化从而找到nlogm或者mlogn的算法;
我们可以采用启发式合并的思路:
用vector Set[MAXN]存储
思路相比于上述蛮力算法不用遍历n次 而是遍历Set对应的vector相应元素大小. 而set对应的元素由1 向n在两者间 逐步增加 优化点在于原先的mn 与现在的m*size;
代码描述如下

vector Set[MAXN];

for(int i=;;){
for(i =0;iID[i]=i;

if(e[i]==1){

//此操作为

    swap(a[i],a[cnt]);
    swap(b[i],b[cnt]);
    swap(c[i],c[cnt]);

}
}
for(int i=0;iif(e[i]==1){
if(set[id[a[i]]]>set[id[b[i]]])swap (set[ida],set[idb]);
for(j =0;iint c =setida;
set[idb].pushback(c);
id[c]=idb;
}else{
if a[i]==b[i]return "No";
}
}
return "Yes"
}
最后我们还可以用并查集外加路径压缩
定义其归属数组() 简称father,合并时设置父节点
定义查找函数 找出其最终归属

int find(int i){
return (father[i]==i)?i:find(father[i]);
}
int Rank[MAXN];
for(i =0;ifor(i =0;i int setA= find(ida);
int setB =find(idb);
if(e[i]==0){
if(setA==setB)return "No";
}else{
//相等条件合并
if(setA>setB){swap(setA,setB);}
if(setA==setB)setB++;
Father[setA]=setB;
}
}return "Yes";

你可能感兴趣的:(c++)