主要思路:
维护两个优先队列,Q1大数优先,存储比中位数小的数;Q2小数优先,存储比中位数大的数;
当存储的数为偶数时,Q1.size() == Q2.size(), 中位数为:(Q1.top() + Q2.top()) / 2.0
当存储的数为奇数时,Q2.size() = Q1.size() + 1, 中位数为 Q2 的队头元素
因此插入元素,要确保Q2.size() >= Q1.size();
同时插入新元素时,要先插入到另一个队列中,确保有序,取队头元素再插入到目的元素中;
#include
#include
#include
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, std::less> Q1; // 大数优先级高,队头
std::priority_queue, std::greater> 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;
}
主要思路:
使用动态规划解决:
#include
#include
class Solution {
public:
int maxSubArray(std::vector& nums) {
int len = nums.size();
if(len == 0) return 0;
std::vector 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 test = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
int Res = S1.maxSubArray(test);
std::cout << Res << std::endl;
return 0;
}
主要思路:视频讲解和题解
规律题,当固定住其中 1 位时,计算其出现1的次数,分别统计个位、百位、千位等数字出现1的个数并求和相加即可;
#include
#include
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;
}
主要思路:视频讲解
规律题,先判断 n 属于哪个范围的数(个位、百位、千位等),再计算 n 具体属于哪一个数,最后计算 n 属于某一个数的具体哪一位,返回即可;
#include
#include
#include
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;
}
主要思路:
拼接字符串 x+y > y+x, 则 x>y;
拼接字符串 x+y < y+x, 则 x
使用快排对字符串数组进行排序,要确保由字符串数组组成的数最小,即strs[0]strs[1]strs[2]...最小,必须连续满足strs[0] < strs[1], strs[1] < strs[2];
#include
#include
#include
class Solution {
public:
std::string minNumber(std::vector& nums) {
std::string Res;
if (nums.size() == 0) return Res;
std::vector strs;
// 数字 -> string
for(int item : nums){
strs.push_back(std::to_string(item));
}
quickSort(strs, 0, nums.size()-1);
for(std::string str : strs){
Res.append(str);
}
return Res;
}
void quickSort(std::vector& strs, int left, int right){
if (left >= right) return;
std::string pivot = strs[left];
int i = left, j = right;
while(i < j){
while(i < j && strs[j] + pivot >= pivot + strs[j]) j--; // 拼接字符串 x+y > y+x, 则 x>y
strs[i] = strs[j];
while(i < j && strs[i] + pivot <= pivot + strs[i]) i++; // 拼接字符串 x+y < y+x, 则 x test = {3, 30, 34, 5, 9};
std::string Res = S1.minNumber(test);
std::cout << Res << std::endl;
return 0;
}