
题目描述
给定一个长度为 n 的整数数组 nums。
下标 i 的得分定义为满足以下条件的索引 j 的数量:
i < j < n nums[j] < nums[i] nums[i] 和 nums[j] 有不同的奇偶性(一个是偶数,另一个是奇数)。
返回一个长度为 n 的整数数组 answer,其中 answer[i] 是下标 i 的得分。
示例 1:
输入:nums = [5,2,4,1,3]
输出:[2,1,2,0,0]
解释:
- 对于
i = 0,元素 nums[1] = 2 和 nums[2] = 4 更小且奇偶性不同。 - 对于
i = 1,元素 nums[3] = 1 更小且奇偶性不同。 - 对于
i = 2,元素 nums[3] = 1 和 nums[4] = 3 更小且奇偶性不同。 - 剩余下标无有效元素。
因此,answer = [2, 1, 2, 0, 0]。
示例 2:
输入:nums = [4,4,1]
输出:[1,1,0]
解释:
对于 i = 0 和 i = 1,元素 nums[2] = 1 更小且奇偶性不同。因此,answer = [1, 1, 0]。
示例 3:
输入:nums = [7]
输出:[0]
解释:
没有元素在下标 0 右侧,因此其得分为 0。因此,answer = [0]。
提示:
1 <= nums.length <= 105 1 <= nums[i] <= 109
解法
方法一:有序列表或树状数组
我们可以使用两个有序列表(或树状数组)分别维护偶数和奇数的元素。对于每个元素,我们查询另一个列表中比它小的元素的数量,并将当前元素添加到对应的列表中。
时间复杂度 \(O(n \times \log n)\),空间复杂度 \(O(n)\)。其中 \(n\) 是数组的长度。
| class Solution:
def countSmallerOppositeParity(self, nums: list[int]) -> list[int]:
n = len(nums)
ans = [0] * n
sl = [SortedList(), SortedList()]
for i in range(n - 1, -1, -1):
ans[i] = sl[nums[i] & 1 ^ 1].bisect_left(nums[i])
sl[nums[i] & 1].add(nums[i])
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 | class BinaryIndexedTree {
int n;
int[] c;
BinaryIndexedTree(int n) {
this.n = n;
this.c = new int[n + 1];
}
void update(int x, int delta) {
while (x <= n) {
c[x] += delta;
x += x & -x;
}
}
int query(int x) {
int s = 0;
while (x > 0) {
s += c[x];
x -= x & -x;
}
return s;
}
}
class Solution {
public int[] countSmallerOppositeParity(int[] nums) {
int n = nums.length;
int[] sorted = nums.clone();
Arrays.sort(sorted);
int m = 0;
for (int i = 0; i < n; i++) {
if (i == 0 || sorted[i] != sorted[i - 1]) {
sorted[m++] = sorted[i];
}
}
BinaryIndexedTree[] bit = {new BinaryIndexedTree(m), new BinaryIndexedTree(m)};
int[] ans = new int[n];
for (int i = n - 1; i >= 0; --i) {
int x = Arrays.binarySearch(sorted, 0, m, nums[i]) + 1;
ans[i] = bit[nums[i] & 1 ^ 1].query(x - 1);
bit[nums[i] & 1].update(x, 1);
}
return ans;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 | struct BIT {
int n;
vector<int> c;
BIT(int n)
: n(n)
, c(n + 1, 0) {}
void update(int x, int delta) {
for (; x <= n; x += x & -x) c[x] += delta;
}
int query(int x) {
int s = 0;
for (; x > 0; x -= x & -x) s += c[x];
return s;
}
};
class Solution {
public:
vector<int> countSmallerOppositeParity(vector<int>& nums) {
int n = nums.size();
vector<int> sorted = nums;
sort(sorted.begin(), sorted.end());
sorted.erase(unique(sorted.begin(), sorted.end()), sorted.end());
int m = sorted.size();
BIT* bits[2] = {new BIT(m), new BIT(m)};
vector<int> ans(n);
for (int i = n - 1; i >= 0; --i) {
int x = lower_bound(sorted.begin(), sorted.end(), nums[i]) - sorted.begin() + 1;
ans[i] = bits[nums[i] & 1 ^ 1]->query(x - 1);
bits[nums[i] & 1]->update(x, 1);
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 | type BIT struct {
n int
c []int
}
func newBIT(n int) *BIT {
return &BIT{n: n, c: make([]int, n+1)}
}
func (b *BIT) update(x, delta int) {
for ; x <= b.n; x += x & -x {
b.c[x] += delta
}
}
func (b *BIT) query(x int) int {
s := 0
for ; x > 0; x -= x & -x {
s += b.c[x]
}
return s
}
func countSmallerOppositeParity(nums []int) []int {
n := len(nums)
sorted := make([]int, n)
copy(sorted, nums)
sort.Ints(sorted)
m := 0
if n > 0 {
m = 1
for i := 1; i < n; i++ {
if sorted[i] != sorted[i-1] {
sorted[m] = sorted[i]
m++
}
}
sorted = sorted[:m]
}
bits := []*BIT{newBIT(m), newBIT(m)}
ans := make([]int, n)
for i := n - 1; i >= 0; i-- {
x := sort.SearchInts(sorted, nums[i]) + 1
ans[i] = bits[nums[i]&1^1].query(x - 1)
bits[nums[i]&1].update(x, 1)
}
return ans
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | class BIT {
private c: Int32Array;
constructor(private n: number) {
this.c = new Int32Array(n + 1);
}
update(x: number, delta: number) {
for (; x <= this.n; x += x & -x) this.c[x] += delta;
}
query(x: number): number {
let s = 0;
for (; x > 0; x -= x & -x) s += this.c[x];
return s;
}
}
function countSmallerOppositeParity(nums: number[]): number[] {
const n = nums.length;
const sorted = _.sortedUniq(_.sortBy(nums));
const m = sorted.length;
const bits = [new BIT(m), new BIT(m)];
const ans = new Array(n);
for (let i = n - 1; i >= 0; i--) {
const rank = _.sortedIndex(sorted, nums[i]) + 1;
ans[i] = bits[(nums[i] & 1) ^ 1].query(rank - 1);
bits[nums[i] & 1].update(rank, 1);
}
return ans;
}
|