Skip to content

Commit d4d5a20

Browse files
committed
Update solution 1649、493
1 parent e0aed6a commit d4d5a20

File tree

10 files changed

+215
-270
lines changed

10 files changed

+215
-270
lines changed

leetcode/0493.Reverse-Pairs/493. Reverse Pairs.go

+62-33
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,69 @@ import (
66
"github.com/halfrost/LeetCode-Go/template"
77
)
88

9-
// 解法一 线段树,时间复杂度 O(n log n)
9+
// 解法一 归并排序 mergesort,时间复杂度 O(n log n)
1010
func reversePairs(nums []int) int {
11+
buf := make([]int, len(nums))
12+
return mergesortCount(nums, buf)
13+
}
14+
15+
func mergesortCount(nums, buf []int) int {
16+
if len(nums) <= 1 {
17+
return 0
18+
}
19+
mid := (len(nums) - 1) / 2
20+
cnt := mergesortCount(nums[:mid+1], buf)
21+
cnt += mergesortCount(nums[mid+1:], buf)
22+
for i, j := 0, mid+1; i < mid+1; i++ { // Note!!! j is increasing.
23+
for ; j < len(nums) && nums[i] <= 2*nums[j]; j++ {
24+
}
25+
cnt += len(nums) - j
26+
}
27+
copy(buf, nums)
28+
for i, j, k := 0, mid+1, 0; k < len(nums); {
29+
if j >= len(nums) || i < mid+1 && buf[i] > buf[j] {
30+
nums[k] = buf[i]
31+
i++
32+
} else {
33+
nums[k] = buf[j]
34+
j++
35+
}
36+
k++
37+
}
38+
return cnt
39+
}
40+
41+
// 解法二 树状数组,时间复杂度 O(n log n)
42+
func reversePairs1(nums []int) (cnt int) {
43+
n := len(nums)
44+
if n <= 1 {
45+
return
46+
}
47+
// 离散化所有下面统计时会出现的元素
48+
allNums := make([]int, 0, 2*n)
49+
for _, v := range nums {
50+
allNums = append(allNums, v, 2*v)
51+
}
52+
sort.Ints(allNums)
53+
k := 1
54+
kth := map[int]int{allNums[0]: k}
55+
for i := 1; i < 2*n; i++ {
56+
if allNums[i] != allNums[i-1] {
57+
k++
58+
kth[allNums[i]] = k
59+
}
60+
}
61+
bit := template.BinaryIndexedTree{}
62+
bit.Init(k)
63+
for i, v := range nums {
64+
cnt += i - bit.Query(kth[2*v])
65+
bit.Add(kth[v], 1)
66+
}
67+
return
68+
}
69+
70+
// 解法三 线段树,时间复杂度 O(n log n)
71+
func reversePairs2(nums []int) int {
1172
if len(nums) < 2 {
1273
return 0
1374
}
@@ -42,35 +103,3 @@ func reversePairs(nums []int) int {
42103
}
43104
return res
44105
}
45-
46-
// 解法二 mergesort
47-
func reversePairs1(nums []int) int {
48-
buf := make([]int, len(nums))
49-
return mergesortCount(nums, buf)
50-
}
51-
52-
func mergesortCount(nums, buf []int) int {
53-
if len(nums) <= 1 {
54-
return 0
55-
}
56-
mid := (len(nums) - 1) / 2
57-
cnt := mergesortCount(nums[:mid+1], buf)
58-
cnt += mergesortCount(nums[mid+1:], buf)
59-
for i, j := 0, mid+1; i < mid+1; i++ { // Note!!! j is increasing.
60-
for ; j < len(nums) && nums[i] <= 2*nums[j]; j++ {
61-
}
62-
cnt += len(nums) - j
63-
}
64-
copy(buf, nums)
65-
for i, j, k := 0, mid+1, 0; k < len(nums); {
66-
if j >= len(nums) || i < mid+1 && buf[i] > buf[j] {
67-
nums[k] = buf[i]
68-
i++
69-
} else {
70-
nums[k] = buf[j]
71-
j++
72-
}
73-
k++
74-
}
75-
return cnt
76-
}

leetcode/0493.Reverse-Pairs/493. Reverse Pairs_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ func Test_Problem493(t *testing.T) {
3131
ans493{2},
3232
},
3333

34+
{
35+
para493{[]int{9, 8, 7, 4, 7, 2, 3, 8, 7, 0}},
36+
ans493{18},
37+
},
38+
3439
{
3540
para493{[]int{2, 4, 3, 5, 1}},
3641
ans493{3},

leetcode/0493.Reverse-Pairs/README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,6 @@ You need to return the number of important reverse pairs in the given array.
3838

3939
- 给出一个数组,要求找出满足条件的所有的“重要的反转对” (i,j)。重要的反转对的定义是:`i<j`,并且 `nums[i] > 2*nums[j]`
4040
- 这一题是 327 题的变种题。首先将数组中所有的元素以及各自的 `2*nums[i] + 1` 都放在字典中去重。去重以后再做离散化处理。这一题的测试用例会卡离散化,如果不离散化,Math.MaxInt32 会导致数字溢出,见测试用例中 2147483647, -2147483647 这组测试用例。离散后,映射关系 保存在字典中。从左往右遍历数组,先 query ,再 update ,这个顺序和第 327 题是反的。先 query 查找 `[2*nums[i] + 1, len(indexMap)-1]` 这个区间内满足条件的值,这个区间内的值都是 `> 2*nums[j]` 的。这一题移动的是 `j`,`j` 不断的变化,往线段树中不断插入的是 `i`。每轮循环先 query 一次前一轮循环中累积插入线段树中的 `i`,这些累积在线段树中的代表的是所有在 `j` 前面的 `i`。query 查询的是本轮 `[2*nums[j] + 1, len(indexMap)-1]`,如果能找到,即找到了这样一个 `j`,能满足 `nums[i] > 2*nums[j`, 把整个数组都扫完,累加的 query 出来的 count 计数就是最终答案。
41+
- 另外一种解法是树状数组。树状数组最擅长解答逆序对的问题。先将原数组中所有的元素值的 2 倍算出来,和原数组合并到一个大数组中。这个大数组中装了所有可能产生 2 倍逆序对的元素值。然后再将他们所有值排序,离散化。离散化以后便将问题集转化成 `[1,N]` 这个区间。于是回到了树状数组经典的求逆序对的问题。逆序插入原数组构造树状数组,或者正序插入原数组构造树状数组都可以解答此题。
4142
- 类似的题目:第 327 题,第 315 题。
42-
- 这一题用线段树并不是最优解,用线段树解这一题是为了训练线段树这个数据结构。最优解是解法二中的 mergesort。
43+
- 这一题用线段树和树状数组并不是最优解,用线段树和树状数组解这一题是为了训练线段树和树状数组这两个数据结构。最优解是解法一中的 mergesort。
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
package leetcode
22

33
import (
4-
"github.com/halfrost/LeetCode-Go/template"
54
"sort"
5+
6+
"github.com/halfrost/LeetCode-Go/template"
67
)
78

8-
// 解法一 线段树 SegmentTree
9+
// 解法一 树状数组 Binary Indexed Tree
910
func createSortedArray(instructions []int) int {
11+
bit, res := template.BinaryIndexedTree{}, 0
12+
bit.Init(100001)
13+
for i, v := range instructions {
14+
less := bit.Query(v - 1)
15+
greater := i - bit.Query(v)
16+
res = (res + min(less, greater)) % (1e9 + 7)
17+
bit.Add(v, 1)
18+
}
19+
return res
20+
}
21+
22+
// 解法二 线段树 SegmentTree
23+
func createSortedArray1(instructions []int) int {
1024
if len(instructions) == 0 {
1125
return 0
1226
}
@@ -49,58 +63,3 @@ func min(a int, b int) int {
4963
}
5064
return a
5165
}
52-
53-
// 解法二 树状数组 Binary Indexed Tree
54-
func createSortedArray1(instructions []int) int {
55-
b := newBIT(make([]int, 100001))
56-
var res int
57-
cnt := map[int]int{}
58-
for i, n := range instructions {
59-
less := b.get(n - 1)
60-
greater := i - less - cnt[n]
61-
res = (res + min(less, greater)) % (1e9 + 7)
62-
b.update(n, 1)
63-
cnt[n]++
64-
}
65-
66-
return res % (1e9 + 7)
67-
}
68-
69-
func max(x, y int) int {
70-
if x > y {
71-
return x
72-
}
73-
return y
74-
}
75-
76-
type BIT struct {
77-
data []int
78-
}
79-
80-
func newBIT(nums []int) *BIT {
81-
data := make([]int, len(nums)+1)
82-
b := &BIT{data}
83-
for i, n := range nums {
84-
b.update(i, n)
85-
}
86-
87-
return b
88-
}
89-
90-
func (b *BIT) update(i, num int) {
91-
i++
92-
for i < len(b.data) {
93-
b.data[i] += num
94-
i += (i & -i)
95-
}
96-
}
97-
98-
func (b *BIT) get(i int) int {
99-
i++
100-
var sum int
101-
for i > 0 {
102-
sum += b.data[i]
103-
i -= (i & -i)
104-
}
105-
return sum
106-
}

leetcode/1649.Create-Sorted-Array-through-Instructions/README.md

+16-56
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,26 @@ The total cost is 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 2 = 4.
8383
package leetcode
8484

8585
import (
86-
"github.com/halfrost/LeetCode-Go/template"
8786
"sort"
87+
88+
"github.com/halfrost/LeetCode-Go/template"
8889
)
8990

90-
// 解法一 线段树 SegmentTree
91+
// 解法一 树状数组 Binary Indexed Tree
9192
func createSortedArray(instructions []int) int {
93+
bit, res := template.BinaryIndexedTree{}, 0
94+
bit.Init(100001)
95+
for i, v := range instructions {
96+
less := bit.Query(v - 1)
97+
greater := i - bit.Query(v)
98+
res = (res + min(less, greater)) % (1e9 + 7)
99+
bit.Add(v, 1)
100+
}
101+
return res
102+
}
103+
104+
// 解法二 线段树 SegmentTree
105+
func createSortedArray1(instructions []int) int {
92106
if len(instructions) == 0 {
93107
return 0
94108
}
@@ -132,58 +146,4 @@ func min(a int, b int) int {
132146
return a
133147
}
134148

135-
// 解法二 树状数组 Binary Indexed Tree
136-
func createSortedArray1(instructions []int) int {
137-
b := newBIT(make([]int, 100001))
138-
var res int
139-
cnt := map[int]int{}
140-
for i, n := range instructions {
141-
less := b.get(n - 1)
142-
greater := i - less - cnt[n]
143-
res = (res + min(less, greater)) % (1e9 + 7)
144-
b.update(n, 1)
145-
cnt[n]++
146-
}
147-
148-
return res % (1e9 + 7)
149-
}
150-
151-
func max(x, y int) int {
152-
if x > y {
153-
return x
154-
}
155-
return y
156-
}
157-
158-
type BIT struct {
159-
data []int
160-
}
161-
162-
func newBIT(nums []int) *BIT {
163-
data := make([]int, len(nums)+1)
164-
b := &BIT{data}
165-
for i, n := range nums {
166-
b.update(i, n)
167-
}
168-
169-
return b
170-
}
171-
172-
func (b *BIT) update(i, num int) {
173-
i++
174-
for i < len(b.data) {
175-
b.data[i] += num
176-
i += (i & -i)
177-
}
178-
}
179-
180-
func (b *BIT) get(i int) int {
181-
i++
182-
var sum int
183-
for i > 0 {
184-
sum += b.data[i]
185-
i -= (i & -i)
186-
}
187-
return sum
188-
}
189149
```

template/BIT.go

+15-16
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,37 @@ type BinaryIndexedTree struct {
77
}
88

99
// Init define
10-
func (bit *BinaryIndexedTree) Init(nums []int, capacity int) {
11-
if len(nums) == 0 {
12-
bit.tree, bit.capacity = make([]int, capacity+1), capacity+1
13-
return
14-
}
15-
bit.tree, bit.capacity = make([]int, len(nums)+1), len(nums)+1
16-
for i := 1; i <= len(nums); i++ {
17-
bit.tree[i] += nums[i-1]
18-
for j := i - 2; j >= i-lowbit(i); j-- {
19-
bit.tree[i] += nums[j]
20-
}
21-
}
10+
func (bit *BinaryIndexedTree) Init(capacity int) {
11+
bit.tree, bit.capacity = make([]int, capacity+1), capacity
2212
}
2313

2414
// Add define
2515
func (bit *BinaryIndexedTree) Add(index int, val int) {
26-
for index <= bit.capacity {
16+
for ; index <= bit.capacity; index += index & -index {
2717
bit.tree[index] += val
28-
index += lowbit(index)
2918
}
3019
}
3120

3221
// Query define
3322
func (bit *BinaryIndexedTree) Query(index int) int {
3423
sum := 0
35-
for index >= 1 {
24+
for ; index > 0; index -= index & -index {
3625
sum += bit.tree[index]
37-
index -= lowbit(index)
3826
}
3927
return sum
4028
}
4129

30+
// InitWithNums define
31+
func (bit *BinaryIndexedTree) InitWithNums(nums []int) {
32+
bit.tree, bit.capacity = make([]int, len(nums)+1), len(nums)
33+
for i := 1; i <= len(nums); i++ {
34+
bit.tree[i] += nums[i-1]
35+
for j := i - 2; j >= i-lowbit(i); j-- {
36+
bit.tree[i] += nums[j]
37+
}
38+
}
39+
}
40+
4241
func lowbit(x int) int {
4342
return x & -x
4443
}

template/BIT_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ import (
77

88
func Test_BIT(t *testing.T) {
99
nums, bit := []int{1, 2, 3, 4, 5, 6, 7, 8}, BinaryIndexedTree{}
10-
bit.Init(nums, 8)
11-
fmt.Printf("%v\n", bit.tree) // [0 1 3 3 10 5 11 7 36]
10+
bit.Init(8)
11+
fmt.Printf("nums = %v bit = %v\n", nums, bit.tree) // [0 1 3 3 10 5 11 7 36]
1212
}

0 commit comments

Comments
 (0)