5.18打卡:劍指 offer兩題:最小k個數/整數1出現的次數

最小k個數

題目描述

輸入n個整數,找出其中最小的K個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,。

class Solution {
public:
    void AdjustHeap(vector<int> &input, int i, int len){
        //i是指從第i個結點開始調整,len是指調整範圍0-len
        int child = 2*i + 1;
        int temp = input[i];
        //遞歸調整法
        if(child < len){//當孩子節點還在調整範圍內纔可以調整,使用下沉調整
            //把大的數下沉
            if(child + 1 < len && input[child + 1] > input[child]){
                child = child + 1;
            }
            if(input[i] < input[child]){
                swap(input[i], input[child]);
                AdjustHeap(input, child, len);
            }
        }
}
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> res;
        if(input.empty() || k > input.size() || k == 0) return res;
         //建堆
        //算法的思想爲維持一個大小爲k的最大堆,再對k以後的元素進行遍歷,如果有元素比堆頂的元素小的,則交換
        //並且繼續調整維持最大堆,這樣當遍歷完所有元素之後,最大堆裏的k個數就是原數組最小的k個數
        //該算法利用最大堆只是爲了方便獲取最大堆裏的最大的元素,並不完全利用堆排序,另一種解法也可以利用堆排序排序完以後再取前k個數
        
        for(int i = (k - 1)/2; i >= 0; i--)
        {
            //AdjustHeap(input, i. k);
            AdjustHeap(input, i, k);
        }
        //for(int i = (k - 1)/2); i >= 0; i --)
            
        int i = k;
        while(i < input.size())
        {
            if(input[0] > input[i])
            {
                swap(input[0],input[i]);
                AdjustHeap(input, 0, k);
            }
            i ++;
        }
        for(int i = 0; i < k; i ++) res.push_back(input[i]);
        
        return res;
    }
};

整數1出現的次數

題目描述

求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?爲此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數(從1 到 n 中1出現的次數)。

思路:

分別計算個位、十位、百位........上出現 1 的個數。以  n =216爲例:個位上: 1 ,11,21,31,.....211。個位上共出現(216/10)+ 1個 1 。因爲除法取整,210~216間個位上的1取不到,所以我們加8進位。你可能說爲什麼不加9,n=211怎麼辦,這裏把最後取到的個位數爲1的單獨考慮,先往下看。十位上:10~19,110~119,210~216.   十位上可看成 求(216/10)=21 個位上的1的個數然後乘10。這裏再次把最後取到的十位數爲1的單獨拿出來,即210~216要單獨考慮 ,個數爲(216%10)+1 .這裏加8就避免了判斷的過程。後面以此類推。時間複雜度 O(logN)

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        int cnt = 0;
        for (int m = 1; m <= n; m *= 10)
        {
            int a = n / m, b = n % m;
            //因爲除法取整,210~216間個位上的1取不到,所以我們加8進位
            cnt += (a + 8) / 10 * m + (a % 10 == 1 ? b + 1 : 0);
        }
        return cnt;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章