剑指offer刷题笔记--Num41-50

1--数据流中的中位数(41)

 主要思路:

      维护两个优先队列,Q1大数优先,存储比中位数小的数;Q2小数优先,存储比中位数大的数;

       当存储的数为偶数时,Q1.size() == Q2.size(), 中位数为:(Q1.top() + Q2.top()) / 2.0

       当存储的数为奇数时,Q2.size() = Q1.size() + 1, 中位数为 Q2 的队头元素

       因此插入元素,要确保Q2.size() >= Q1.size();

       同时插入新元素时,要先插入到另一个队列中,确保有序,取队头元素再插入到目的元素中;

#include <iostream>
#include <queue>   
#include <algorithm>

class MedianFinder {
public:
    MedianFinder() {}
    
    void addNum(int num) {
        // Q1大数优先,存储比中位数小的数
        // Q2小数优先,存储比中位数大的数
        // 当存储的数为偶数时,Q1.size() == Q2.size(), 中位数为:(Q1.top() + Q2.top()) / 2.0
        // 当存储的数为奇数时,Q2.size() = Q1.size() + 1, 中位数为 Q2 的队头元素
        // 因此插入元素,要确保Q2.size() >= Q1.size(); 
        // 同时插入新元素时,要先插入到另一个队列中,确保有序,取队头元素再插入到目的元素中
        if(Q1.size() == Q2.size()){
            Q1.push(num);
            int top = Q1.top();
            Q1.pop();
            Q2.push(top);
        }
        else{
            Q2.push(num);
            int top = Q2.top();
            Q2.pop();
            Q1.push(top);
        }
    }
    
    double findMedian() {
        if(Q1.size() == Q2.size()){
            return (Q1.top() + Q2.top()) / 2.0;
        }
        else{
            return Q2.top()*1.0;
        }
        
    }
private:
    std::priority_queue<int, std::vector<int>, std::less<int>> Q1; // 大数优先级高,队头
    std::priority_queue<int, std::vector<int>, std::greater<int>> Q2; // 小数优先级高,队头
};


int main(int argc, char *argv[]){
    MedianFinder S1;
    S1.addNum(1);
    S1.addNum(4);
    S1.addNum(2);
    S1.addNum(3);
    double Res = S1.findMedian();
    std::cout << Res << std::endl;
    return 0;
}

2--连续子数组的最大和(42)

主要思路:

        使用动态规划解决: 

#include <iostream>
#include <vector>

class Solution {
public:
    int maxSubArray(std::vector<int>& nums) {
        int len = nums.size();
        if(len == 0) return 0;

        std::vector<int> dp;
        dp.push_back(nums[0]);
        int max = nums[0];
        for(int i = 1; i < len; i++){
            if(dp[i - 1] >= 0){
                dp.push_back(dp[i-1] + nums[i]);
            }
            else{
                dp.push_back(nums[i]);
            }
            if (dp[i] > max) max = dp[i];
        }
        return max;
    }
};

int main(int argc, char *argv[]){
    Solution S1;
    std::vector<int> test = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
    int Res = S1.maxSubArray(test);
    std::cout << Res << std::endl;
    return 0;
}

3--1~n中整数中 1 出现的次数(43)

主要思路:视频讲解题解

        规律题,当固定住其中 1 位时,计算其出现1的次数,分别统计个位、百位、千位等数字出现1的个数并求和相加即可;

#include <iostream>
#include <vector>

class Solution {
public:
    int countDigitOne(int n) {
        long long bit = 1;
        long long sum = 0;
        while(bit <= n){
            long long cur = n / bit % 10;
            long long low = n % bit;
            long long high = n / bit / 10;
            if(cur == 0){
                sum += high * bit;
            }
            else if(cur == 1){
                sum += high*bit + low + 1;
            }
            else{
                sum += (high+1)*bit;
            }
            bit = bit*10;
        }
        return (int)sum;
    }
};

int main(int argc, char *argv[]){
    Solution S1;
    int test = 12;
    int sum = S1.countDigitOne(test);
    std::cout << sum << std::endl;
    return 0;
}

4--数字序列中某一位的数字(44)

主要思路:视频讲解

        规律题,先判断 n 属于哪个范围的数(个位、百位、千位等),再计算 n 具体属于哪一个数,最后计算 n 属于某一个数的具体哪一位,返回即可;

#include <iostream>
#include <vector>
#include <cmath>

class Solution {
public:
    int findNthDigit(int n) {
        if(n == 0) return 0;
        long bit = 1; // 1 10 100
        int i = 1; // 1 2 3
        long count = 9; // 9 180 2700 // 范围内字符的个数 
        // 确定属于哪一个范围
        while(count < n){
            n = n - count;
            i = i + 1;
            bit = bit * 10;
            count = bit * i * 9;
        }
        // 确定属于哪一个数
        long num = bit + (n-1) / i;
        // 确定具体哪一位
        int index = (n - 1) % i + 1;
        int res = (int)(num / pow(10, i - index)) % 10;
        return res;
    }
};

int main(int argc, char *argv[]){
    Solution S1;
    int test = 19;
    int res = S1.findNthDigit(test);
    std::cout << res << std::endl;
    return 0;
}

5--把数组排成最小的数(45)

猜你喜欢

转载自blog.csdn.net/weixin_43863869/article/details/131630355