【貪心法】奇數陣列 思路解析和程式碼

九筒-發表於2020-10-31

奇數陣列

輸入正整數n和長度為n(? ≤ 105)的數列??(1 ≤ a? ≤ 109)。在一次操作中你可以選擇一個偶數c,並且把所有等於c的數除以2。例如a = [6,8,12,6,3,12],選擇c = 6進行一次操作後a = [3,8,12,3,3,12]。請問最少進行多少次操作後, ?? 的所有數都變成奇數。請嘗試設計演算法進行計算。
樣例輸入
6
40 6 40 3 20 1
樣例輸出
4

個人思路

思路

本題應該採用貪心策略,每次選擇陣列中最大的偶數作為運算元,然後遍歷整個陣列並對與運算元相等的數進行除2操作,直到陣列中全部為奇數為止

貪心策略證明:設當前有四個偶數並滿足a > b > c > d。根據貪心策略,第一次取運算元為a,得到陣列[a/2,b,c,d]:

  • if(a/2 > b),第二次運算元為a/2,得到的陣列為[a/4,b,c,d]
  • else if(a/2 == b),第二次運算元為a/2,得到的陣列為[a/4,b/2,c,d]
  • else(即a/2 < b),第二次運算元為b,得到的陣列為[a/2,b/2,c,d]

顯然取最大的數字作為運算元時,有可能同時對兩個及以上個數的元素進行除2操作,因此是最優選擇

注意

  • 使用雙端佇列deque,便於在初始化時對陣列進行排序操作
  • deque中只儲存偶數元素
  • 操作過程中,如果出現偶數直接刪去
  • 每次對deque遍歷後,要對序列進行排序,由於此時序列基本有序,因此採用插排更有效率

個人思路程式碼

/*
 * @Author: LLX 
 * @Date: 2020-10-31 19:19:03 
 * @Last Modified by: SEUer
 * @Last Modified time: 2020-10-31 21:03:58
 */
//記錄偶數,記錄最大的數字
#include<bits/stdc++.h>
using namespace std;
deque<int> arr;
int n, ans;
void insertSort(){//對於基本有序的陣列,插排效率更高
    int index = 0;
    for(int i = 1; i < n; ++i){
        if(arr[index] < arr[i]){
            swap(arr[index], arr[i]);
            index = i;
        }else{
            break;
        }
    }
}
void display(){
    for(int i = 0; i < arr.size(); ++i){
        cout << arr[i] << " ";
    }
    cout << endl;
}
int main(){
    int firstnum;
    scanf("%d%d", &n, &firstnum);
    arr.push_back(firstnum);
    for(int i = 1; i < n; ++i){
        int num;
        scanf("%d", &num);
        if(num % 2 == 0){//arr中只存在偶數
            if(num > arr[0])
                arr.push_front(num);
            else
                arr.push_back(num);
        }
    }
    display();
    while(arr.size() > 0){
        int c = arr[0];//取整個陣列當前最大偶數
        ans++;
        cout << "******第" << ans << "次*******" << endl;
        for(auto j = arr.begin(); j != arr.end(); ++j){
            if(arr.size() == 0){
                break;
            }
            if(*j == c)
                *j /= 2;
            if(*j % 2 == 1)//除2之後為奇數,則出隊
            arr.erase(j);
            insertSort();
            display();
        }
    } 
    cout << ans << endl;
    system("pause");
    return 0;
}
/*
4
56 16 24 40
*/

相關文章