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(t[mid]>=nums[i]){
right= mid;
}
else{
left=mid+1;
}
}
res[i]=right;
t.insert(t.begin()+right,nums[i]);
}
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({nums[i], 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)
b[i] = a[i];
int i = l, j = mid + 1, k = l;
while (i <= mid || j <= r)
{
if (i > mid)
a[k++] = b[j++];
else if (j > r)
a[k++] = b[i++];
else if (b[i].first <= b[j].first)
a[k++] = b[j++];//逆序合并
else
{
res[b[i].second] += r - j + 1;
a[k++] = b[i++];
}
}
}
};
树状数组
const int MAXN = 100007;
int cnt[MAXN],n;
/*数组cnt[i]用于记录出现元素nums[i]的个数*/
class Solution {
public:
inline void add(int k)
{
for(; k <= n; k += -k&k) cnt[k] += 1;
}
int sum(int k)
{
int res = 0;
for(; k; k -= -k&k) res += cnt[k];
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({nums[i], i+1});
}
memset(cnt, 0, sizeof(cnt));
sort(A.begin(), A.end());
/*进行排序*/
for(int i = 0; i < n; i ++) {
int id = A[i].second;
int t = sum(n) - sum(id);
ans[id-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(nums[n-1]);
int count_small;
for(int i = 1;i < n;i++)
{
count_small = 0;
BST_insert(node,new BSTNode(nums[n-i-1]),count_small);
count.push_back(count_small);
}
/*最后不要忘记删除树节点*/
delete node;
reverse(count.begin(),count.end());
/*push_back的时候是逆序的,此时只要将count数组reverse即可*/
return count;
}
};