归并|线段树|树状数组

lc315

树状数组应该是最优

暴力的二分..

class Solution {

public:

vector<int> countSmaller(vector<int>& nums) {

vector<int>t,res(nums.size());

      /*初始化t,res*/

for(int i=nums.size()-1;i>=0;i--){

int left=0,right=t.size();

        /*下面是一个在t数组里二分查找的过程*/

while (left<right){

int mid=left+(right-left)/2;

if(tmid>=numsi){

right= mid;

}

else{

left=mid+1;

}

}

resi=right;

t.insert(t.begin()+right,numsi);

}

return res;

}

};

归并

class Solution

{

public:

vector<pair<int, int>> a, b;

vector<int> res;

vector<int> countSmaller(vector<int> &nums)

{

int n = nums.size();

for (int i = 0; i < n; ++i)

a.push_back({numsi, i});

b.resize(n);

res.resize(n);

dfs(0, n - 1);

return res;

}

void dfs(int l, int r)

{

if (l == r)

return;

int mid = (l + r) >> 1;

// 归并是后序遍历的统计模式 所以我们先递归 再合并。

dfs(l, mid);

dfs(mid + 1, r);

for (int i = l; i <= r; ++i)

bi = ai;

int i = l, j = mid + 1, k = l;

while (i <= mid || j <= r)

{

if (i > mid)

ak++ = bj++;

else if (j > r)

ak++ = bi++;

else if (bi.first <= bj.first)

ak++ = bj++;//逆序合并

else

{

resb\[i.second] += r - j + 1;

ak++ = bi++;

}

}

}

};

树状数组

const int MAXN = 100007;

int cntMAXN,n;

/*数组cnti用于记录出现元素numsi的个数*/

class Solution {

public:

inline void add(int k)

{

for(; k <= n; k += -k&k) cntk += 1;

}

int sum(int k)

{

int res = 0;

for(; k; k -= -k&k) res += cntk;

return res;

}

vector<int> countSmaller(vector<int>& nums) {

n = nums.size();

vector<int> ans(n);

vector<pair<int, int>> A;

/*建立一个从数组内容到未排序前索引的映射A*/

for(int i = 0; i < n; i ++) {

A.push_back({numsi, i+1});

}

memset(cnt, 0, sizeof(cnt));

sort(A.begin(), A.end());

/*进行排序*/

for(int i = 0; i < n; i ++) {

int id = Ai.second;

int t = sum(n) - sum(id);

ansid-1 = t;

add(id);

}

return ans;

}

};

二叉搜索树

struct BSTNode{

int val;

int count;

BSTNode *left;

BSTNode *right;

BSTNode(int x)

: val(x)

, left(NULL)

, right(NULL)

, count(0)

{}

};

/*建立一个二分查找树,每个树结点有四个值,分别是:

int val;这个结点代表的值val

int count;这个val代表的次数也就是在nums数组种比val小的数的个数

left 左子树指针

right 右子树指针

一个构造函数,构造函数如上定义

*/

void BST_insert(BSTNode *node,BSTNode *insert_node,int &count_small)

{

if(node->val >= insert_node->val)

{

/*插入的结点更小,被比较结点(即node)的count++,然后插入到左子树(如果不为空)*/

node->count++;

if(node->left)

{

BST_insert(node->left,insert_node,count_small);

}

else

{

/*左子树为空,插入结点就作为当前结点的左孩子*/

node->left = insert_node;

}

}

else{

/*插入的结点更大,需要在右子树(如果不为空)继续找*/

count_small += node->count + 1;

if(node->right)

{

BST_insert(node->right,insert_node,count_small);

}

else

{

/*当前右子树为空,插入结点作为当前结点右孩子*/

node->right = insert_node;

}

}

}

/*count_small作为一个引用的参数,在递归寻找子树的时候作为一个"类似全局变量"的存在*/

class Solution {

public:

vector<int> countSmaller(vector<int>& nums) {

int n=nums.size();

/*如果数组为空返回空值*/

if(n==0)return {};

vector<int> count;

count.push_back(0);

/*建立一个二叉搜素树*/

BSTNode* node=new BSTNode(numsn-1);

int count_small;

for(int i = 1;i < n;i++)

{

count_small = 0;

BST_insert(node,new BSTNode(numsn-i-1),count_small);

count.push_back(count_small);

}

/*最后不要忘记删除树节点*/

delete node;

reverse(count.begin(),count.end());

/*push_back的时候是逆序的,此时只要将count数组reverse即可*/

return count;

}

};

相关推荐
炸膛坦客7 小时前
单片机/C/C++八股:(二十六)IIC 专题(I²C)---- 上集
c语言·c++·单片机
旖-旎7 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题
Henry Zhu1238 小时前
C++中的特殊成员函数与智能指针
c++
_wyt00110 小时前
多重背包问题详解
c++·背包dp
Ljwuhe11 小时前
C++——多态
开发语言·c++
越甲八千11 小时前
STL stack为何没有迭代器
c++
从零开始的代码生活_13 小时前
C++ 继承详解:访问控制、对象模型、菱形继承与设计取舍
开发语言·c++·后端·学习·算法
云小逸13 小时前
【C++ 第七阶段:模板、泛型编程与工程综合详解】
开发语言·c++
GIS阵地14 小时前
QgsSingleBandPseudoColorRenderer 完整详解(QGIS 3.40.13 C++)
开发语言·前端·c++·qt·qgis
王维同学14 小时前
[原创][Windows C++]LSA 认证、安全与通知包的注册表枚举
c++·windows·安全