Array Binary Indexed Tree Binary Search Divide and Conquer Merge Sort Ordered Set Segment Tree Treap
Description Given an integer array nums, return the number of reverse pairs in the array .
A reverse pair is a pair (i, j) where:
0 <= i < j < nums.length and nums[i] > 2 * nums[j].
Example 1:
Input: nums = [1,3,2,3,1]
Output: 2
Explanation: The reverse pairs are:
(1, 4) --> nums[1] = 3, nums[4] = 1, 3 > 2 * 1
(3, 4) --> nums[3] = 3, nums[4] = 1, 3 > 2 * 1
Example 2:
Input: nums = [2,4,3,5,1]
Output: 3
Explanation: The reverse pairs are:
(1, 4) --> nums[1] = 4, nums[4] = 1, 4 > 2 * 1
(2, 4) --> nums[2] = 3, nums[4] = 1, 3 > 2 * 1
(3, 4) --> nums[3] = 5, nums[4] = 1, 5 > 2 * 1
Constraints:
1 <= nums.length <= 5 * 104 -231 <= nums[i] <= 231 - 1 Solutions Solution 1 Thinking
A reverse pair is \(i<j\) and \(nums[i]>2\,nums[j]\) . A double loop is \(O(n^2)\) . During mergesort both halves are sorted, so cross pairs can be counted before merging.
Recurse on both halves, then for each right value advance a left pointer until \(nums[i]>2\,nums[j]\) ; the leftover left side all form pairs. Merge by raw value afterwards.
Counting and merging stay separate: the count compares against \(2\,nums[j]\) , the merge compares the original values.
Python3 Java C++ Go
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 class Solution :
def reversePairs ( self , nums : List [ int ]) -> int :
def merge_sort ( l , r ):
if l >= r :
return 0
mid = ( l + r ) >> 1
ans = merge_sort ( l , mid ) + merge_sort ( mid + 1 , r )
t = []
i , j = l , mid + 1
while i <= mid and j <= r :
if nums [ i ] <= 2 * nums [ j ]:
i += 1
else :
ans += mid - i + 1
j += 1
i , j = l , mid + 1
while i <= mid and j <= r :
if nums [ i ] <= nums [ j ]:
t . append ( nums [ i ])
i += 1
else :
t . append ( nums [ j ])
j += 1
t . extend ( nums [ i : mid + 1 ])
t . extend ( nums [ j : r + 1 ])
nums [ l : r + 1 ] = t
return ans
return merge_sort ( 0 , len ( nums ) - 1 )
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 Solution {
private int [] nums ;
private int [] t ;
public int reversePairs ( int [] nums ) {
this . nums = nums ;
int n = nums . length ;
this . t = new int [ n ] ;
return mergeSort ( 0 , n - 1 );
}
private int mergeSort ( int l , int r ) {
if ( l >= r ) {
return 0 ;
}
int mid = ( l + r ) >> 1 ;
int ans = mergeSort ( l , mid ) + mergeSort ( mid + 1 , r );
int i = l , j = mid + 1 , k = 0 ;
while ( i <= mid && j <= r ) {
if ( nums [ i ] <= nums [ j ] * 2L ) {
++ i ;
} else {
ans += mid - i + 1 ;
++ j ;
}
}
i = l ;
j = mid + 1 ;
while ( i <= mid && j <= r ) {
if ( nums [ i ] <= nums [ j ] ) {
t [ k ++] = nums [ i ++] ;
} else {
t [ k ++] = nums [ j ++] ;
}
}
while ( i <= mid ) {
t [ k ++] = nums [ i ++] ;
}
while ( j <= r ) {
t [ k ++] = nums [ j ++] ;
}
for ( i = l ; i <= r ; ++ i ) {
nums [ i ] = t [ i - l ] ;
}
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 class Solution {
public :
int reversePairs ( vector < int >& nums ) {
int n = nums . size ();
int t [ n ];
function < int ( int , int ) > mergeSort = [ & ]( int l , int r ) -> int {
if ( l >= r ) {
return 0 ;
}
int mid = ( l + r ) >> 1 ;
int ans = mergeSort ( l , mid ) + mergeSort ( mid + 1 , r );
int i = l , j = mid + 1 , k = 0 ;
while ( i <= mid && j <= r ) {
if ( nums [ i ] <= nums [ j ] * 2L L ) {
++ i ;
} else {
ans += mid - i + 1 ;
++ j ;
}
}
i = l ;
j = mid + 1 ;
while ( i <= mid && j <= r ) {
if ( nums [ i ] <= nums [ j ]) {
t [ k ++ ] = nums [ i ++ ];
} else {
t [ k ++ ] = nums [ j ++ ];
}
}
while ( i <= mid ) {
t [ k ++ ] = nums [ i ++ ];
}
while ( j <= r ) {
t [ k ++ ] = nums [ j ++ ];
}
for ( i = l ; i <= r ; ++ i ) {
nums [ i ] = t [ i - l ];
}
return ans ;
};
return mergeSort ( 0 , n - 1 );
}
};
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 func reversePairs ( nums [] int ) int {
n := len ( nums )
t := make ([] int , n )
var mergeSort func ( l , r int ) int
mergeSort = func ( l , r int ) int {
if l >= r {
return 0
}
mid := ( l + r ) >> 1
ans := mergeSort ( l , mid ) + mergeSort ( mid + 1 , r )
i , j , k := l , mid + 1 , 0
for i <= mid && j <= r {
if nums [ i ] <= nums [ j ] * 2 {
i ++
} else {
ans += mid - i + 1
j ++
}
}
i , j = l , mid + 1
for i <= mid && j <= r {
if nums [ i ] <= nums [ j ] {
t [ k ] = nums [ i ]
k , i = k + 1 , i + 1
} else {
t [ k ] = nums [ j ]
k , j = k + 1 , j + 1
}
}
for ; i <= mid ; i , k = i + 1 , k + 1 {
t [ k ] = nums [ i ]
}
for ; j <= r ; j , k = j + 1 , k + 1 {
t [ k ] = nums [ j ]
}
for i = l ; i <= r ; i ++ {
nums [ i ] = t [ i - l ]
}
return ans
}
return mergeSort ( 0 , n - 1 )
}
Solution 2 Thinking
Solution 1 rewrites the array. After discretizing \(nums\) and \(2\,nums\) , walk right to left, insert \(2\,nums[j]\) into a Fenwick tree, and query how many inserted values are less than \(nums[i]\) .
The relative order of the original array is not needed beyond the right-to-left scan; the tree stores the \(2\,nums\) already seen.
Python3 Java C++ Go
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 class BinaryIndexedTree :
def __init__ ( self , n ):
self . n = n
self . c = [ 0 ] * ( n + 1 )
@staticmethod
def lowbit ( x ):
return x & - x
def update ( self , x , delta ):
while x <= self . n :
self . c [ x ] += delta
x += BinaryIndexedTree . lowbit ( x )
def query ( self , x ):
s = 0
while x > 0 :
s += self . c [ x ]
x -= BinaryIndexedTree . lowbit ( x )
return s
class Solution :
def reversePairs ( self , nums : List [ int ]) -> int :
s = set ()
for num in nums :
s . add ( num )
s . add ( num * 2 )
alls = sorted ( s )
m = { v : i for i , v in enumerate ( alls , 1 )}
ans = 0
tree = BinaryIndexedTree ( len ( m ))
for num in nums [:: - 1 ]:
ans += tree . query ( m [ num ] - 1 )
tree . update ( m [ num * 2 ], 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
52 class Solution {
public int reversePairs ( int [] nums ) {
TreeSet < Long > ts = new TreeSet <> ();
for ( int num : nums ) {
ts . add (( long ) num );
ts . add (( long ) num * 2 );
}
Map < Long , Integer > m = new HashMap <> ();
int idx = 0 ;
for ( long num : ts ) {
m . put ( num , ++ idx );
}
BinaryIndexedTree tree = new BinaryIndexedTree ( m . size ());
int ans = 0 ;
for ( int i = nums . length - 1 ; i >= 0 ; -- i ) {
int x = m . get (( long ) nums [ i ] );
ans += tree . query ( x - 1 );
tree . update ( m . get (( long ) nums [ i ] * 2 ), 1 );
}
return ans ;
}
}
class BinaryIndexedTree {
private int n ;
private int [] c ;
public BinaryIndexedTree ( int n ) {
this . n = n ;
c = new int [ n + 1 ] ;
}
public void update ( int x , int delta ) {
while ( x <= n ) {
c [ x ] += delta ;
x += lowbit ( x );
}
}
public int query ( int x ) {
int s = 0 ;
while ( x > 0 ) {
s += c [ x ] ;
x -= lowbit ( x );
}
return s ;
}
public static int lowbit ( int x ) {
return x & - x ;
}
}
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 class BinaryIndexedTree {
public :
int n ;
vector < int > c ;
BinaryIndexedTree ( int _n )
: n ( _n )
, c ( _n + 1 ) {}
void update ( int x , int delta ) {
while ( x <= n ) {
c [ x ] += delta ;
x += lowbit ( x );
}
}
int query ( int x ) {
int s = 0 ;
while ( x > 0 ) {
s += c [ x ];
x -= lowbit ( x );
}
return s ;
}
int lowbit ( int x ) {
return x & - x ;
}
};
class Solution {
public :
int reversePairs ( vector < int >& nums ) {
set < long long > s ;
for ( int num : nums ) {
s . insert ( num );
s . insert ( num * 2l l );
}
unordered_map < long long , int > m ;
int idx = 0 ;
for ( long long num : s ) m [ num ] = ++ idx ;
BinaryIndexedTree * tree = new BinaryIndexedTree ( m . size ());
int ans = 0 ;
for ( int i = nums . size () - 1 ; i >= 0 ; -- i ) {
ans += tree -> query ( m [ nums [ i ]] - 1 );
tree -> update ( m [ nums [ i ] * 2l l ], 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
52
53 type BinaryIndexedTree struct {
n int
c [] int
}
func newBinaryIndexedTree ( n int ) * BinaryIndexedTree {
c := make ([] int , n + 1 )
return & BinaryIndexedTree { n , c }
}
func ( this * BinaryIndexedTree ) lowbit ( x int ) int {
return x & - x
}
func ( this * BinaryIndexedTree ) update ( x , delta int ) {
for x <= this . n {
this . c [ x ] += delta
x += this . lowbit ( x )
}
}
func ( this * BinaryIndexedTree ) query ( x int ) int {
s := 0
for x > 0 {
s += this . c [ x ]
x -= this . lowbit ( x )
}
return s
}
func reversePairs ( nums [] int ) int {
s := make ( map [ int ] bool )
for _ , num := range nums {
s [ num ] = true
s [ num * 2 ] = true
}
var alls [] int
for num := range s {
alls = append ( alls , num )
}
sort . Ints ( alls )
m := make ( map [ int ] int )
for i , num := range alls {
m [ num ] = i + 1
}
tree := newBinaryIndexedTree ( len ( m ))
ans := 0
for i := len ( nums ) - 1 ; i >= 0 ; i -- {
ans += tree . query ( m [ nums [ i ]] - 1 )
tree . update ( m [ nums [ i ] * 2 ], 1 )
}
return ans
}
Solution 3 Thinking
Replace the Fenwick tree with a segment tree: same discretization, insert \(2\,nums\) from the right, query the count below \(nums[i]\) . Same algebra, with explicit interval nodes.
Python3 Java C++
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
52
53
54
55
56
57
58
59
60
61
62 class Node :
def __init__ ( self ):
self . l = 0
self . r = 0
self . v = 0
class SegmentTree :
def __init__ ( self , n ):
self . tr = [ Node () for _ in range ( 4 * n )]
self . build ( 1 , 1 , n )
def build ( self , u , l , r ):
self . tr [ u ] . l = l
self . tr [ u ] . r = r
if l == r :
return
mid = ( l + r ) >> 1
self . build ( u << 1 , l , mid )
self . build ( u << 1 | 1 , mid + 1 , r )
def modify ( self , u , x , v ):
if self . tr [ u ] . l == x and self . tr [ u ] . r == x :
self . tr [ u ] . v += 1
return
mid = ( self . tr [ u ] . l + self . tr [ u ] . r ) >> 1
if x <= mid :
self . modify ( u << 1 , x , v )
else :
self . modify ( u << 1 | 1 , x , v )
self . pushup ( u )
def pushup ( self , u ):
self . tr [ u ] . v = self . tr [ u << 1 ] . v + self . tr [ u << 1 | 1 ] . v
def query ( self , u , l , r ):
if self . tr [ u ] . l >= l and self . tr [ u ] . r <= r :
return self . tr [ u ] . v
mid = ( self . tr [ u ] . l + self . tr [ u ] . r ) >> 1
v = 0
if l <= mid :
v += self . query ( u << 1 , l , r )
if r > mid :
v += self . query ( u << 1 | 1 , l , r )
return v
class Solution :
def reversePairs ( self , nums : List [ int ]) -> int :
s = set ()
for num in nums :
s . add ( num )
s . add ( num * 2 )
alls = sorted ( s )
m = { v : i for i , v in enumerate ( alls , 1 )}
tree = SegmentTree ( len ( m ))
ans = 0
for v in nums [:: - 1 ]:
x = m [ v ]
ans += tree . query ( 1 , 1 , x - 1 )
tree . modify ( 1 , m [ v * 2 ], 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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 class Solution {
public int reversePairs ( int [] nums ) {
TreeSet < Long > ts = new TreeSet <> ();
for ( int num : nums ) {
ts . add (( long ) num );
ts . add (( long ) num * 2 );
}
Map < Long , Integer > m = new HashMap <> ();
int idx = 0 ;
for ( long num : ts ) {
m . put ( num , ++ idx );
}
SegmentTree tree = new SegmentTree ( m . size ());
int ans = 0 ;
for ( int i = nums . length - 1 ; i >= 0 ; -- i ) {
int x = m . get (( long ) nums [ i ] );
ans += tree . query ( 1 , 1 , x - 1 );
tree . modify ( 1 , m . get (( long ) nums [ i ] * 2 ), 1 );
}
return ans ;
}
}
class Node {
int l ;
int r ;
int v ;
}
class SegmentTree {
private Node [] tr ;
public SegmentTree ( int n ) {
tr = new Node [ 4 * n ] ;
for ( int i = 0 ; i < tr . length ; ++ i ) {
tr [ i ] = new Node ();
}
build ( 1 , 1 , n );
}
public void build ( int u , int l , int r ) {
tr [ u ] . l = l ;
tr [ u ] . r = r ;
if ( l == r ) {
return ;
}
int mid = ( l + r ) >> 1 ;
build ( u << 1 , l , mid );
build ( u << 1 | 1 , mid + 1 , r );
}
public void modify ( int u , int x , int v ) {
if ( tr [ u ] . l == x && tr [ u ] . r == x ) {
tr [ u ] . v += v ;
return ;
}
int mid = ( tr [ u ] . l + tr [ u ] . r ) >> 1 ;
if ( x <= mid ) {
modify ( u << 1 , x , v );
} else {
modify ( u << 1 | 1 , x , v );
}
pushup ( u );
}
public void pushup ( int u ) {
tr [ u ] . v = tr [ u << 1 ] . v + tr [ u << 1 | 1 ] . v ;
}
public int query ( int u , int l , int r ) {
if ( tr [ u ] . l >= l && tr [ u ] . r <= r ) {
return tr [ u ] . v ;
}
int mid = ( tr [ u ] . l + tr [ u ] . r ) >> 1 ;
int v = 0 ;
if ( l <= mid ) {
v += query ( u << 1 , l , r );
}
if ( r > mid ) {
v += query ( u << 1 | 1 , l , r );
}
return v ;
}
}
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 class Node {
public :
int l ;
int r ;
int v ;
};
class SegmentTree {
public :
vector < Node *> tr ;
SegmentTree ( int n ) {
tr . resize ( 4 * n );
for ( int i = 0 ; i < tr . size (); ++ i ) tr [ i ] = new Node ();
build ( 1 , 1 , n );
}
void build ( int u , int l , int r ) {
tr [ u ] -> l = l ;
tr [ u ] -> r = r ;
if ( l == r ) return ;
int mid = ( l + r ) >> 1 ;
build ( u << 1 , l , mid );
build ( u << 1 | 1 , mid + 1 , r );
}
void modify ( int u , int x , int v ) {
if ( tr [ u ] -> l == x && tr [ u ] -> r == x ) {
tr [ u ] -> v += v ;
return ;
}
int mid = ( tr [ u ] -> l + tr [ u ] -> r ) >> 1 ;
if ( x <= mid )
modify ( u << 1 , x , v );
else
modify ( u << 1 | 1 , x , v );
pushup ( u );
}
void pushup ( int u ) {
tr [ u ] -> v = tr [ u << 1 ] -> v + tr [ u << 1 | 1 ] -> v ;
}
int query ( int u , int l , int r ) {
if ( tr [ u ] -> l >= l && tr [ u ] -> r <= r ) return tr [ u ] -> v ;
int mid = ( tr [ u ] -> l + tr [ u ] -> r ) >> 1 ;
int v = 0 ;
if ( l <= mid ) v = query ( u << 1 , l , r );
if ( r > mid ) v += query ( u << 1 | 1 , l , r );
return v ;
}
};
class Solution {
public :
int reversePairs ( vector < int >& nums ) {
set < long long > s ;
for ( int num : nums ) {
s . insert ( num );
s . insert ( num * 2l l );
}
unordered_map < long long , int > m ;
int idx = 0 ;
for ( long long num : s ) m [ num ] = ++ idx ;
SegmentTree * tree = new SegmentTree ( m . size ());
int ans = 0 ;
for ( int i = nums . size () - 1 ; i >= 0 ; -- i ) {
ans += tree -> query ( 1 , 1 , m [ nums [ i ]] - 1 );
tree -> modify ( 1 , m [ nums [ i ] * 2l l ], 1 );
}
return ans ;
}
};
GitHub