广联达笔试第三题0909/数组中按照一定规则删除重复元素

题目描述:

我们希望一个序列中的元素是各不相同的,但是理想和现实往往是有差距的。现在给出一个序列A,其中难免有些相同的元素,现在提供了一种变化方式,使得经过若干次操作后一定可以得到一个元素各不相同的序列。

这个操作是这样的,令x为序列中最小的有重复的数字,你需要删除序列左数第一个x,并把第二个x替换为2*x。

请你输出最终的序列。

例如原序列是[2,2,1,1,1],一次变换后变为[2,2,2,1],两次变换后变为[4,2,1],变换结束

输入描述
输入第一行包含一个正整数n,表示序列的长度为n。(1<=n<=50000)

第二行有n个整数,初始序列中的元素。(1<=a_i<=10^8)

输出描述
输出包含若干个整数,即最终变换之后的结果。

样例输入
5
5 5 5 5 4
样例输出
20 4

基本思想:

  • 将元素保存在链表中,便于从任意位置删除
  • 同时将元素保存在优先队列中(使得元素从小到大排列),便于找到最小的元素
  • 队列非空时,执行如下循环:
    判断队头元素是否是重复元素,如果是则将第一次出现的删掉,将第二次出现的变为2倍,并加入优先队列中。
    这里为了便于删除元素,需要用一个变量来保存元素的位置。
#include<bits/stdc++.h>

using namespace std;

int main(){
    
        
    int n;
    cin >> n;
    list<int> ls;
    priority_queue<int, vector<int>, greater<int>> pq;//从小到大
    for(int i = 0; i < n; ++i){
    
    //将元素存入链表的同时,存入优先队列中
        int t;
        cin >> t;
        ls.push_back(t);
        pq.push(t);
    }


    while(!pq.empty()){
    
    
        int val = pq.top();
        pq.pop();
        //检查该元素是否重复
        int cnt = 0;
        auto pre = ls.begin();
        for(auto iter = ls.begin(); iter != ls.end(); ++iter){
    
    
            if(*iter == val){
    
    
                ++cnt;                
                if(cnt > 1){
    
    
                    *iter = *iter * 2;
                    pq.push(*iter);   
                    ls.erase(pre);                 
                    break;
                }
                pre = iter;//这个语句一定要放在if判断条件之后,目的是保存第一次出现重复元素的位置
            }            
        }
    }


    for(auto iter = ls.begin(); iter != ls.end(); ++iter){
    
    
        cout << *iter << " ";    
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_31672701/article/details/108523093