11/*
2- * Copyright 2018-2021 Vincent A. Cicirello, <https://www.cicirello.org/>.
2+ * JavaPermutationTools: A Java library for computation on permutations and sequences.
3+ * Copyright (C) 2018-2021 Vincent A. Cicirello, <https://www.cicirello.org/>.
34 *
45 * This file is part of JavaPermutationTools (https://jpt.cicirello.org/).
56 *
7677 * Industrial Networks and Intelligent Systems, 7(23), Article e1, April 2020.</p>
7778 *
7879 * @author <a href=https://www.cicirello.org/ target=_top>Vincent A. Cicirello</a>, <a href=https://www.cicirello.org/ target=_top>https://www.cicirello.org/</a>
79- * @version 5.13.2021
8080 */
8181public final class KendallTauSequenceDistance implements SequenceDistanceMeasurer {
8282
@@ -128,7 +128,7 @@ public int distance(int[] s1, int[] s2) {
128128 int numLabels = USE_HASHMAP ? relabelElementsWithHash (s1 ,s2 ,relabeling ) : relabelElements (s1 ,s2 ,relabeling );
129129 Bucket [][] buckets = bucketSortElements (relabeling , numLabels );
130130 int [] mapping = mapElements (buckets , relabeling .length );
131- return countInversions (mapping );
131+ return countInversions (mapping , 0 , mapping . length - 1 );
132132 }
133133
134134 /**
@@ -144,7 +144,7 @@ public int distance(long[] s1, long[] s2) {
144144 int numLabels = USE_HASHMAP ? relabelElementsWithHash (s1 ,s2 ,relabeling ) : relabelElements (s1 ,s2 ,relabeling );
145145 Bucket [][] buckets = bucketSortElements (relabeling , numLabels );
146146 int [] mapping = mapElements (buckets , relabeling .length );
147- return countInversions (mapping );
147+ return countInversions (mapping , 0 , mapping . length - 1 );
148148 }
149149
150150 /**
@@ -160,7 +160,7 @@ public int distance(short[] s1, short[] s2) {
160160 int numLabels = USE_HASHMAP ? relabelElementsWithHash (s1 ,s2 ,relabeling ) : relabelElements (s1 ,s2 ,relabeling );
161161 Bucket [][] buckets = bucketSortElements (relabeling , numLabels );
162162 int [] mapping = mapElements (buckets , relabeling .length );
163- return countInversions (mapping );
163+ return countInversions (mapping , 0 , mapping . length - 1 );
164164 }
165165
166166 /**
@@ -176,7 +176,7 @@ public int distance(byte[] s1, byte[] s2) {
176176 int numLabels = USE_HASHMAP ? relabelElementsWithHash (s1 ,s2 ,relabeling ) : relabelElements (s1 ,s2 ,relabeling );
177177 Bucket [][] buckets = bucketSortElements (relabeling , numLabels );
178178 int [] mapping = mapElements (buckets , relabeling .length );
179- return countInversions (mapping );
179+ return countInversions (mapping , 0 , mapping . length - 1 );
180180 }
181181
182182 /**
@@ -192,7 +192,7 @@ public int distance(char[] s1, char[] s2) {
192192 int numLabels = USE_HASHMAP ? relabelElementsWithHash (s1 ,s2 ,relabeling ) : relabelElements (s1 ,s2 ,relabeling );
193193 Bucket [][] buckets = bucketSortElements (relabeling , numLabels );
194194 int [] mapping = mapElements (buckets , relabeling .length );
195- return countInversions (mapping );
195+ return countInversions (mapping , 0 , mapping . length - 1 );
196196 }
197197
198198 /**
@@ -208,7 +208,7 @@ public int distance(String s1, String s2) {
208208 int numLabels = USE_HASHMAP ? relabelElementsWithHash (s1 ,s2 ,relabeling ) : relabelElements (s1 ,s2 ,relabeling );
209209 Bucket [][] buckets = bucketSortElements (relabeling , numLabels );
210210 int [] mapping = mapElements (buckets , relabeling .length );
211- return countInversions (mapping );
211+ return countInversions (mapping , 0 , mapping . length - 1 );
212212 }
213213
214214 /**
@@ -224,7 +224,7 @@ public int distance(float[] s1, float[] s2) {
224224 int numLabels = USE_HASHMAP ? relabelElementsWithHash (s1 ,s2 ,relabeling ) : relabelElements (s1 ,s2 ,relabeling );
225225 Bucket [][] buckets = bucketSortElements (relabeling , numLabels );
226226 int [] mapping = mapElements (buckets , relabeling .length );
227- return countInversions (mapping );
227+ return countInversions (mapping , 0 , mapping . length - 1 );
228228 }
229229
230230 /**
@@ -240,7 +240,7 @@ public int distance(double[] s1, double[] s2) {
240240 int numLabels = USE_HASHMAP ? relabelElementsWithHash (s1 ,s2 ,relabeling ) : relabelElements (s1 ,s2 ,relabeling );
241241 Bucket [][] buckets = bucketSortElements (relabeling , numLabels );
242242 int [] mapping = mapElements (buckets , relabeling .length );
243- return countInversions (mapping );
243+ return countInversions (mapping , 0 , mapping . length - 1 );
244244 }
245245
246246 /**
@@ -256,7 +256,7 @@ public int distance(boolean[] s1, boolean[] s2) {
256256 int numLabels = relabelElements (s1 ,s2 ,relabeling );
257257 Bucket [][] buckets = bucketSortElements (relabeling , numLabels );
258258 int [] mapping = mapElements (buckets , relabeling .length );
259- return countInversions (mapping );
259+ return countInversions (mapping , 0 , mapping . length - 1 );
260260 }
261261
262262 /**
@@ -277,7 +277,7 @@ public int distance(Object[] s1, Object[] s2) {
277277
278278 Bucket [][] buckets = bucketSortElements (relabeling , numLabels );
279279 int [] mapping = mapElements (buckets , relabeling .length );
280- return countInversions (mapping );
280+ return countInversions (mapping , 0 , mapping . length - 1 );
281281 }
282282
283283 /**
@@ -296,7 +296,7 @@ public <T> int distance(List<T> s1, List<T> s2) {
296296
297297 Bucket [][] buckets = bucketSortElements (relabeling , numLabels );
298298 int [] mapping = mapElements (buckets , relabeling .length );
299- return countInversions (mapping );
299+ return countInversions (mapping , 0 , mapping . length - 1 );
300300 }
301301
302302 private int [] mapElements (Bucket [][] buckets , int seqLength ) {
@@ -752,15 +752,21 @@ private int relabelElements(List<Comparable> s1, List<Comparable> s2, int[][] re
752752 }
753753
754754 // assumes all unique elements
755- private int countInversions (int [] array ) {
756- if (array .length <= 1 ) return 0 ;
757- int m = array .length / 2 ;
758- int [] left = Arrays .copyOfRange (array , 0 , m );
759- int [] right = Arrays .copyOfRange (array , m , array .length );
760- int count = countInversions (left ) + countInversions (right );
755+ private int countInversions (int [] array , int first , int last ) {
756+ if (last <= first ) {
757+ return 0 ;
758+ }
759+ int m = (first + last ) >> 1 ;
760+ return countInversions (array , first , m ) + countInversions (array , m +1 , last ) + merge (array , first , m +1 , last +1 );
761+ }
762+
763+ private int merge (int [] array , int first , int midPlus , int lastPlus ) {
764+ int [] left = Arrays .copyOfRange (array , first , midPlus );
765+ int [] right = Arrays .copyOfRange (array , midPlus , lastPlus );
761766 int i = 0 ;
762767 int j = 0 ;
763- int k = 0 ;
768+ int k = first ;
769+ int count = 0 ;
764770 while (i < left .length && j < right .length ) {
765771 if (left [i ] <= right [j ]) {
766772 array [k ] = left [i ];
@@ -787,6 +793,7 @@ private int countInversions(int[] array) {
787793 return count ;
788794 }
789795
796+
790797 // internal data structures below
791798
792799 private static final class Bucket {
0 commit comments