1649. 通过指令创建有序数组
给你一个整数数组 instructions
,你需要根据 instructions
中的元素创建一个有序数组。一开始你有一个空的数组 nums
,你需要 从左到右 遍历 instructions
中的元素,将它们依次插入 nums
数组中。每一次插入操作的 代价 是以下两者的 较小值 :
nums
中 严格小于 instructions[i]
的数字数目。nums
中 严格大于 instructions[i]
的数字数目。比方说,如果要将 3
插入到 nums = [1,2,3,5]
,那么插入操作的 代价 为 min(2, 1)
(元素 1
和 2
小于 3
,元素 5
大于 3
),插入后 nums
变成 [1,2,3,3,5]
。
请你返回将 instructions
中所有元素依次插入 nums
后的 总最小代价 。由于答案会很大,请将它对 109 + 7
取余 后返回。
示例 1:
输入:instructions = [1,5,6,2] 输出:1 解释:一开始 nums = [] 。 插入 1 ,代价为 min(0, 0) = 0 ,现在 nums = [1] 。 插入 5 ,代价为 min(1, 0) = 0 ,现在 nums = [1,5] 。 插入 6 ,代价为 min(2, 0) = 0 ,现在 nums = [1,5,6] 。 插入 2 ,代价为 min(1, 2) = 1 ,现在 nums = [1,2,5,6] 。 总代价为 0 + 0 + 0 + 1 = 1 。
示例 2:
输入:instructions = [1,2,3,6,5,4] 输出:3 解释:一开始 nums = [] 。 插入 1 ,代价为 min(0, 0) = 0 ,现在 nums = [1] 。 插入 2 ,代价为 min(1, 0) = 0 ,现在 nums = [1,2] 。 插入 3 ,代价为 min(2, 0) = 0 ,现在 nums = [1,2,3] 。 插入 6 ,代价为 min(3, 0) = 0 ,现在 nums = [1,2,3,6] 。 插入 5 ,代价为 min(3, 1) = 1 ,现在 nums = [1,2,3,5,6] 。 插入 4 ,代价为 min(3, 2) = 2 ,现在 nums = [1,2,3,4,5,6] 。 总代价为 0 + 0 + 0 + 0 + 1 + 2 = 3 。
示例 3:
输入:instructions = [1,3,3,3,2,4,2,1,2] 输出:4 解释:一开始 nums = [] 。 插入 1 ,代价为 min(0, 0) = 0 ,现在 nums = [1] 。 插入 3 ,代价为 min(1, 0) = 0 ,现在 nums = [1,3] 。 插入 3 ,代价为 min(1, 0) = 0 ,现在 nums = [1,3,3] 。 插入 3 ,代价为 min(1, 0) = 0 ,现在 nums = [1,3,3,3] 。 插入 2 ,代价为 min(1, 3) = 1 ,现在 nums = [1,2,3,3,3] 。 插入 4 ,代价为 min(5, 0) = 0 ,现在 nums = [1,2,3,3,3,4] 。 插入 2 ,代价为 min(1, 4) = 1 ,现在 nums = [1,2,2,3,3,3,4] 。 插入 1 ,代价为 min(0, 6) = 0 ,现在 nums = [1,1,2,2,3,3,3,4] 。 插入 2 ,代价为 min(2, 4) = 2 ,现在 nums = [1,1,2,2,2,3,3,3,4] 。 总代价为 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 2 = 4 。
提示:
1 <= instructions.length <= 105
1 <= instructions[i] <= 105
原站题解
php 解法, 执行用时: 1024 ms, 内存消耗: 31.3 MB, 提交时间: 2023-10-08 23:29:30
class BIT { private $n; private $tree; function __construct($n) { $this->n = $n; $this->tree = array_fill(0, $n + 1, 0); } function lowbit($x) { return $x & (-$x); } function update($x) { while ($x <= $this->n) { ++$this->tree[$x]; $x += $this->lowbit($x); } } function query($x) { $ans = 0; while ($x) { $ans += $this->tree[$x]; $x -= $this->lowbit($x); } return $ans; } } class Solution { /** * @param int[] $instructions * @return Integer */ function createSortedArray($instructions) { $bit = new BIT(max($instructions)); $ans = 0; for ($i = 0; $i < count($instructions); ++$i) { $x = $instructions[$i]; $smaller = $bit->query($x - 1); $larger = $i - $bit->query($x); $ans += min($smaller, $larger); $bit->update($x); } return $ans % 1000000007; } }
java 解法, 执行用时: 96 ms, 内存消耗: 63.5 MB, 提交时间: 2023-10-08 23:28:57
class Solution { public int createSortedArray(int[] instructions) { int mod = (int)1e9 + 7; long ans = 0; Set<Integer> set = new HashSet<>(); for(int i = 0; i < instructions.length; ++i) { set.add(instructions[i]); } int[] nums = new int[set.size()]; int index = 0; for(int num: set) { nums[index++] = num; } Arrays.sort(nums); Map<Integer, Integer> map = new HashMap<>(); for(int i = 0; i < nums.length; ++i) { map.put(nums[i], i + 1); } BIT bit = new BIT(nums.length); for(int i = 0; i < instructions.length; ++i) { int t = map.get(instructions[i]); int l = bit.getSum(t - 1); int r = bit.getSum(t); // System.out.println(l); // System.out.println(r); ans += Math.min(l, i - r); ans %= mod; bit.update(t, 1); } return (int) ans; } } class BIT { int n; int[] tree; public BIT(int n) { this.n = n; tree = new int[n + 1]; } public void update(int i, int val) { while(i <= n) { tree[i] += val; i += lowbit(i); } } public int getSum(int i) { int res = 0; while(i > 0) { res += tree[i]; i -= lowbit(i); } return res; } public int lowbit(int x) { return x & (-x); } }
golang 解法, 执行用时: 184 ms, 内存消耗: 9.2 MB, 提交时间: 2023-10-08 23:28:20
func createSortedArray(instructions []int) (cnt int) { mod := 1000000007 tree := make([]int, 100001) var sum func(i int) int sum = func(i int) (x int) { for j := i; j > 0; j -= (j & -j) { x += tree[j] } return } for _, i := range instructions { for j := i; j < len(tree); j += (j & -j) { tree[j]++ } cnt = (cnt + min(sum(i-1), sum(100000)-sum(i))) % mod } return } func min(a, b int) int { if a < b { return a }; return b }
golang 解法, 执行用时: 200 ms, 内存消耗: 14.1 MB, 提交时间: 2023-10-08 23:27:49
var ( nums, tree []int ) func lowbit(x int) int { return x&(-x) } func add(i, v int) { for i <= len(nums) { tree[i] += v i += lowbit(i) } } func sum(i int) int { res := 0 for i > 0 { res += tree[i] i -= lowbit(i) } return res } func sumFromTo(i, j int) int { return sum(j)-sum(i-1) } func createSortedArray(instructions []int) int { MOD := 1000000007 min := func(a, b int) int { if a < b { return a } return b } nums = make([]int, 100000) tree = make([]int, len(nums)*2) res := 0 for i := range instructions { lessCount := sum(instructions[i]-1) largerCount := i - sum(instructions[i]) res += min(lessCount, largerCount) res %= MOD add(instructions[i], 1) } return res }
python3 解法, 执行用时: 2452 ms, 内存消耗: 27.7 MB, 提交时间: 2023-10-08 23:27:17
class Solution: def createSortedArray(self, instructions: List[int]) -> int: def add(x: int) -> None: # 将x插入到树状数组中 while x < n: nums[x] += 1 x += (x & -x) def getSum(x: int) -> int: # 求出小于等于x的元素个数 res = 0 while x > 0: res += nums[x] x -= (x & -x) return res # 创建树状数组 n = max(instructions) + 1 nums = [0 for _ in range(n)] # res为总代价 res = 0 # cnt为当前存在元素 cnt = 0 for i in instructions: # getSum(i-1)求比自己小的元素个数 # cnt - getSum(i)求比自己大的元素个数 res = (res + min(getSum(i - 1), cnt - getSum(i))) % (10 ** 9 + 7) add(i) cnt += 1 return res
python3 解法, 执行用时: 4228 ms, 内存消耗: 28.2 MB, 提交时间: 2023-10-08 23:26:53
class Solution: def createSortedArray(self, instructions: List[int]) -> int: ans = 0 ordered = list() for x in instructions: smaller = bisect.bisect_left(ordered, x) larger = len(ordered) - bisect.bisect_right(ordered, x) ans += min(smaller, larger) ordered[smaller:smaller] = [x] return ans % (10**9 + 7)
cpp 解法, 执行用时: 744 ms, 内存消耗: 224.3 MB, 提交时间: 2023-10-08 23:26:36
class BalancedTree { private: struct BalancedNode { int val; int seed; int count; int size; BalancedNode* left; BalancedNode* right; BalancedNode(int _val, int _seed): val(_val), seed(_seed), count(1), size(1), left(nullptr), right(nullptr) {} BalancedNode* left_rotate() { int prev_size = size; int curr_size = (left ? left->size : 0) + (right->left ? right->left->size : 0) + count; BalancedNode* root = right; right = root->left; root->left = this; root->size = prev_size; size = curr_size; return root; } BalancedNode* right_rotate() { int prev_size = size; int curr_size = (right ? right->size : 0) + (left->right ? left->right->size : 0) + count; BalancedNode* root = left; left = root->right; root->right = this; root->size = prev_size; size = curr_size; return root; } }; private: BalancedNode* root; int size; mt19937 gen; uniform_int_distribution<int> dis; private: BalancedNode* insert_(BalancedNode* node, int x) { if (!node) { return new BalancedNode(x, dis(gen)); } ++node->size; if (x < node->val) { node->left = insert_(node->left, x); if (node->left->seed > node->seed) { node = node->right_rotate(); } } else if (x > node->val) { node->right = insert_(node->right, x); if (node->right->seed > node->seed) { node = node->left_rotate(); } } else { ++node->count; } return node; } public: BalancedTree(): root(nullptr), size(0), gen(random_device{}()), dis(INT_MIN, INT_MAX) {} int get_size() const { return size; } void insert(int x) { ++size; root = insert_(root, x); } int lower_bound(int x) const { BalancedNode* node = root; int ans = INT_MAX; while (node) { if (x == node->val) { return x; } if (x < node->val) { ans = node->val; node = node->left; } else { node = node->right; } } return ans; } int upper_bound(int x) const { BalancedNode* node = root; int ans = INT_MAX; while (node) { if (x < node->val) { ans = node->val; node = node->left; } else { node = node->right; } } return ans; } pair<int, int> rank(int x) const { BalancedNode* node = root; int ans = 0; while (node) { if (x < node->val) { node = node->left; } else { ans += (node->left ? node->left->size : 0) + node->count; if (x == node->val) { return {ans - node->count + 1, ans}; } node = node->right; } } return {INT_MIN, INT_MAX}; } }; class Solution { private: static constexpr int mod = 1000000007; public: int createSortedArray(vector<int>& instructions) { BalancedTree treap; long long ans = 0; for (int i = 0; i < instructions.size(); ++i) { int x = instructions[i]; int lb = treap.lower_bound(x); int smaller = (lb == INT_MAX ? i : treap.rank(lb).first - 1); int rb = treap.upper_bound(x); int larger = (rb == INT_MAX ? 0 : i - treap.rank(rb).first + 1); ans += min(smaller, larger); treap.insert(x); } return ans % mod; } };
cpp 解法, 执行用时: 232 ms, 内存消耗: 114.2 MB, 提交时间: 2023-10-08 23:26:20
class BIT { private: int n; vector<int> tree; public: BIT(int _n): n(_n), tree(_n + 1) {} static constexpr int lowbit(int x) { return x & (-x); } void update(int x) { while (x <= n) { ++tree[x]; x += lowbit(x); } } int query(int x) const { int ans = 0; while (x) { ans += tree[x]; x -= lowbit(x); } return ans; } }; class Solution { private: static constexpr int mod = 1000000007; public: int createSortedArray(vector<int>& instructions) { int ub = *max_element(instructions.begin(), instructions.end()); BIT bit(ub); long long ans = 0; for (int i = 0; i < instructions.size(); ++i) { int x = instructions[i]; int smaller = bit.query(x - 1); int larger = i - bit.query(x); ans += min(smaller, larger); bit.update(x); } return ans % mod; } };
cpp 解法, 执行用时: 512 ms, 内存消耗: 121.3 MB, 提交时间: 2023-10-08 23:26:09
class SegTree { private: int n; vector<int> segnode; private: void update_(int id, int l, int r, int x) { if (l > x || r < x) { return; } ++segnode[id]; if (l == r) { return; } int mid = (l + r) >> 1; update_(id * 2 + 1, l, mid, x); update_(id * 2 + 2, mid + 1, r, x); } int query_(int id, int l, int r, int ql, int qr) const { if (l > qr || r < ql) { return 0; } if (ql <= l && r <= qr) { return segnode[id]; } int mid = (l + r) >> 1; return query_(id * 2 + 1, l, mid, ql, qr) + query_(id * 2 + 2, mid + 1, r, ql, qr); } public: SegTree(int _n): n(_n), segnode(_n * 4) {} void update(int x) { update_(0, 1, n, x); } int query(int left, int right) const { return query_(0, 1, n, left, right); } }; class Solution { private: static constexpr int mod = 1000000007; public: int createSortedArray(vector<int>& instructions) { int ub = *max_element(instructions.begin(), instructions.end()); SegTree tree(ub); long long ans = 0; for (int i = 0; i < instructions.size(); ++i) { int x = instructions[i]; int smaller = tree.query(1, x - 1); int larger = tree.query(x + 1, ub); ans += min(smaller, larger); tree.update(x); } return ans % mod; } };