from bisect import bisect_left, bisect_right, insort
class FenwickTree:
def __init__(self, size):
self.n = size + 2
self.tree = [0] * (self.n)
def update(self, index, delta):
while index < self.n:
self.tree[index] += delta
index += index & -index
def query(self, index):
result = 0
while index > 0:
result += self.tree[index]
index -= index & -index
return result
class Solution:
def createSortedArray(self, instructions):
MOD = 10**9 + 7
max_val = max(instructions)
ft = FenwickTree(max_val)
cost = 0
for i, num in enumerate(instructions):
left = ft.query(num - 1)
right = i - ft.query(num)
cost = (cost + min(left, right)) % MOD
ft.update(num, 1)
return cost
class FenwickTree {
vector<int> tree;
int n;
public:
FenwickTree(int size) : n(size + 2), tree(n, 0) {}
void update(int index, int delta) {
while (index < n) {
tree[index] += delta;
index += index & -index;
}
}
int query(int index) {
int result = 0;
while (index > 0) {
result += tree[index];
index -= index & -index;
}
return result;
}
};
class Solution {
public:
int createSortedArray(vector<int>& instructions) {
const int MOD = 1e9 + 7;
int maxVal = *max_element(instructions.begin(), instructions.end());
FenwickTree ft(maxVal);
int cost = 0;
for (int i = 0; i < instructions.size(); ++i) {
int num = instructions[i];
int left = ft.query(num - 1);
int right = i - ft.query(num);
cost = (cost + min(left, right)) % MOD;
ft.update(num, 1);
}
return cost;
}
};
class FenwickTree {
int[] tree;
int n;
FenwickTree(int size) {
n = size + 2;
tree = new int[n];
}
void update(int index, int delta) {
while (index < n) {
tree[index] += delta;
index += index & -index;
}
}
int query(int index) {
int result = 0;
while (index > 0) {
result += tree[index];
index -= index & -index;
}
return result;
}
}
class Solution {
public int createSortedArray(int[] instructions) {
int MOD = 1000000007;
int maxVal = 0;
for (int num : instructions) maxVal = Math.max(maxVal, num);
FenwickTree ft = new FenwickTree(maxVal);
int cost = 0;
for (int i = 0; i < instructions.length; ++i) {
int num = instructions[i];
int left = ft.query(num - 1);
int right = i - ft.query(num);
cost = (cost + Math.min(left, right)) % MOD;
ft.update(num, 1);
}
return cost;
}
}
class FenwickTree {
constructor(size) {
this.n = size + 2;
this.tree = new Array(this.n).fill(0);
}
update(index, delta) {
while (index < this.n) {
this.tree[index] += delta;
index += index & -index;
}
}
query(index) {
let result = 0;
while (index > 0) {
result += this.tree[index];
index -= index & -index;
}
return result;
}
}
var createSortedArray = function(instructions) {
const MOD = 1e9 + 7;
let maxVal = Math.max(...instructions);
let ft = new FenwickTree(maxVal);
let cost = 0;
for (let i = 0; i < instructions.length; ++i) {
let num = instructions[i];
let left = ft.query(num - 1);
let right = i - ft.query(num);
cost = (cost + Math.min(left, right)) % MOD;
ft.update(num, 1);
}
return cost;
};
You are given an array of integers called instructions
. You need to create a sorted array by inserting the elements from instructions
one by one, from left to right.
When inserting instructions[i]
into the array, the cost is defined as the minimum of:
instructions[i]
already present in the arrayinstructions[i]
already present in the array10^9 + 7
.
At first glance, the problem seems to require counting, for each number, how many elements are less than and greater than it in a dynamically growing array. A brute-force way would be to scan the array each time, but that would be too slow for large inputs.
We realize that we need a way to efficiently count the number of elements less than or greater than a given value, as the array grows. This is a classic use-case for data structures that support fast prefix sums or order statistics, such as Binary Indexed Trees (Fenwick Trees) or Segment Trees.
The key insight is that we do not need to maintain the array in sorted order; we only need to know, for each number, how many smaller and greater numbers have already been inserted, and do so quickly.
To solve this efficiently, we use a Fenwick Tree (also known as a Binary Indexed Tree). This data structure allows us to:
instructions
.instructions
:
num - 1
).num
).num
.10^9 + 7
.
Consider instructions = [1,5,6,2]
:
Brute-force approach:
instructions
.instructions
.The key insight is to use a Fenwick Tree to efficiently count how many numbers less than or greater than a given value have been inserted so far. This allows us to calculate the cost of each insertion in logarithmic time, making the solution feasible for large inputs. The elegance of the solution lies in recognizing that we do not need to actually sort or maintain the array, only to count efficiently, which is what the Fenwick Tree excels at.