归并|线段树|树状数组

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;

}

};

相关推荐
Qt程序员4 小时前
Linux RCU 原理与应用
linux·c++·内核·linux内核·rcu
qeen874 小时前
【C++】类与对象之类的默认成员函数(二)
android·c语言·开发语言·c++·笔记·学习
王老师青少年编程5 小时前
信奥赛C++提高组csp-s之搜索进阶(记忆化搜索案例实践3)
c++·记忆化搜索·方格取数·csp·信奥赛·csp-s·提高组
Titan20246 小时前
Linux动静态库
linux·服务器·c++
j_xxx404_6 小时前
MySQL表操作硬核解析:从 CREATE TABLE 到磁盘文件、ALTER TABLE 与 DDL 风险
运维·服务器·数据库·c++·mysql·adb·ai
wuminyu7 小时前
Java锁机制之park和unpark源码剖析
java·linux·c语言·jvm·c++
玖玥拾7 小时前
C/C++ 基础笔记(十一)类的进阶
c语言·c++·设计模式·
-森屿安年-8 小时前
1137. 第 N 个泰波那契数
c++·动态规划
程序员老舅8 小时前
从内核视角,看Linux文件读写过程
linux·服务器·c++·内核·linux内核·vfs·linux内存
Soari8 小时前
llama.cpp更新(b9553):LLM inference in C/C++,本地和云端实现高性能大模型推理
c语言·c++·llama