10

I want to find out the rank of each element in an array starting from 0.

For example:

arr = {2, 1,3 } 
rank will be {1,0 ,2}

Explanation:

rank of 2 is 1 because 2 is greater than exactly 1 element
rank of 1 is 0 because 1 is greater than exactly  0  element
rank of 3 is 2 because 1 is greater than exactly  2  element

What I have tried is n^2 time complexity algorithm. I want an algorithm with linear time complexity O(n).

Someone gave me solution for it in the comment section below but his comment has been deleted I don't know how. Which is correctly working for negative integers and positive integers as well as very large size of list.

Thanks to the author

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

class rank{
    public static void main(String args[]){
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(2);
        list.add(1);
        list.add(3);
        ArrayList<Integer> listCopy = new ArrayList<Integer>(list);

        Collections.sort(list); // sorting array
         //   System.out.println("List : " + listCopy);
         //  System.out.println("Sorted List : " + list);

        Map<Integer, Integer> rankMap = new HashMap<Integer, Integer>();
        int counter = 0;
        for(int x : list) {
            rankMap.put(x, counter); 
            // list value as key and rank as  value.
            counter++;
        }
        StringBuffer sb=new StringBuffer();
        for(int x : listCopy) {
            sb.append(rankMap.get(x) + " "); 
            // System.out.println(map.get(x));
        }
        System.out.println( sb.toString().substring(0, sb.length()-1))
    }
}
Bilesh Ganguly
  • 3,792
  • 3
  • 36
  • 58
Syed Shibli
  • 992
  • 1
  • 12
  • 15
  • What about sorting the array? The index of each element will be its rank. However it probably won't be in linear time. – Kevin Aug 10 '15 at 11:39
  • 1
    sort a copy of the array - remove duplicates - compare the ints in the first array to the index of the int in the sorted array with unique elements – Stultuske Aug 10 '15 at 11:41
  • will counting sort works?? – Syed Shibli Aug 10 '15 at 11:42
  • If you could find the rank of all the elements in linear time, then you could sort by (a) finding the rank (linear), (b) assigning the elements based on the rank (also linear). So you would have linear sort. Since this is impossible, so is a rank-finding linear algorithm. – RealSkeptic Aug 10 '15 at 11:42
  • bro array me contain negative integers.. – Syed Shibli Aug 10 '15 at 11:43
  • 1
    @RealSkeptic You're right except that in a special cases (where the type of data allows it) it is possible to sort in linear time. Think of radix sort for example. – Kevin Aug 10 '15 at 11:44
  • 1
    @HyperZ the linearity of radix sort is questionable (the width of a word is bounded by log n). – RealSkeptic Aug 10 '15 at 11:48
  • {2, 1,3 } after sorting it became{ 1 ,2, 3} than rank will be{ 0,1,2} bro this is not what i am asking ans should be{ 1,0,2 } – Syed Shibli Aug 10 '15 at 11:52
  • [Sorting in linear time?](http://stackoverflow.com/questions/749585/sorting-in-linear-time) – Naman Gala Aug 10 '15 at 12:27
  • some body gives me an code below down in comment section which is correctly working for very large size of n..but know his comment has been deleted i dont know how...... – Syed Shibli Aug 10 '15 at 12:45
  • what about array containing duplicate elements ? {1,2,2,3,4 } what should we print as rank of the two successive 2's ? – mounaim Aug 10 '15 at 13:39

7 Answers7

3

So with rank you mean the position where this element would end up after sorting the array?

You can start with a identity mapping map = {0,1,2} and then sort that, but using your arr as sort key.

Collections.sort(map, (c1, c2) -> arr[c2] > arr[c1] ? +1 : arr[c2] == arr[c1] ? 0 : -1);

This way you won't change your original array, but get a mapping from your array elements to its rank.

Obviously this algorithm depends on the complexity of your sort algorithm. You should end up with O(n log n) but maybe your data allows to use sorting algorithms with O(n) complexity. But that really depends on what you store in your big list.

Tali
  • 861
  • 8
  • 17
  • `c1` and `c2` here are parameters of a lambda expression. See http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html. – Tali Sep 21 '15 at 07:57
  • `arr[c2]-arr[c1]` might break if the difference is big enough. – Prabhu Sep 07 '16 at 03:10
  • @Prabhu: is there some other comparison operator available in Java which can be used for `sort`? – Tali Sep 15 '16 at 12:21
  • @Tail, If the numbers are too big e.g. -2147483648 and +2147483647, then answer does not fit in 32 bits, and it returns garbage so it fails. You have to use if operation to return -1 if first less than second, 0 on equal and 1 on greater. – Prabhu Sep 16 '16 at 05:08
  • @Prabhu, yeah, sure. But is there any simple function which does this comparison, returning pos/zero/neg? I don't want to blow up the above example code too much. – Tali Sep 16 '16 at 06:39
  • 1
    A quick hand-coded version would be `arr[c2] > arr[c1] ? +1 : arr[c2] == arr[c1] ? 0 : -1` – Tali Sep 16 '16 at 06:41
1

at first sort all element and store in a another array (if elements is unsorted) then print element index from that array .

Osman Goni Nahid
  • 1,193
  • 2
  • 15
  • 24
1

Use radix sort to sort your array in linear time. Each element will be in its own rank.

uoyilmaz
  • 3,035
  • 14
  • 25
  • {2, 1,3 } after sorting it became{ 1 ,2, 3} than rank will be{ 0,1,2} bro this is not what i am asking ans should be{ 1,0,2 } – Syed Shibli Aug 10 '15 at 11:50
1

I give an idea. If you want, you can use this:

It's applicable if array value[0....n-1]
  1. Firstly create a count_array from input array by counting sort technique( Ex: array = {2, 1, 3}, So count_array = { 0,1,1,1} // here array value use as count_array index value).
  2. Then you can filter count_array like result_array = {0, 1, 2, 3} // you only add 1 with previous added value if count_array[i] == 1 (you can also do that in count_array. I use result _array for just understanding)
  3. Then you make a rank_array from result_array By rank_array[i] = result_array[array[i]] - 1
  4. Finally you can find your rank_array with O(n)

Example:

array = {2,1,3} 
count_array = {0,1,1,1}
result_array = {0,1,2,3}
rank_array = {1,0,2} //rank_array[i] = result_array[array[i]] - 1
Sakib Ahammed
  • 2,452
  • 2
  • 25
  • 29
1

in java 8, first array to list, then to stream. because of only one loop in stream, it should be O(n).

Integer[] arr = {2, 1,3 };
List <Integer> list = Arrays.asList(arr);
Integer[] outArr  = list.stream()
        .sorted()
        .map(e -> list.indexOf(e))
        .toArray(Integer[]::new);

result:{1,0,2}

  • 1
    This does not work if you have several identical entries in your array. And of course, the `sorted()` has complexity O(n log n). – Tali Sep 16 '16 at 06:38
1

You can use a map to map the index in the array to the value, sort on the values and return the indexes. It could look like this:

private static int[] ranks(int[] array) {
  Map<Integer, Integer> m = new HashMap<> ();
  for (int i = 0; i < array.length; i++) {
    m.put(i, array[i]);
  }
  return m.entrySet().stream()
                  .sorted(Entry.comparingByValue())
                  .mapToInt(Entry::getKey)
                  .toArray();
}

Example usage:

int[] ranks = ranks(new int[] { 2, 1, 3 });
System.out.println(Arrays.toString(ranks)); //outputs {1, 0, 2}
assylias
  • 321,522
  • 82
  • 660
  • 783
1

It is possible to compute this rank using a data structure called "Order statistic tree", it is a augmented data structure. In order to implement this structure you must implement a balanced binary tree (e.g. AVL-Tree or Red-Black Tree) and you add an additional attribute to each node. This is a very efficient way to compute ranks because it takes O(lg n) (where lg is base 2 logarithm) for each element. You can find more information about this data structure in "Introduction to Algorithms" in Chapter 14.

The problem with the sorting is that its running time is O(nlog(n)) and I think that it is inefficient if you want to rank few elements (i.e. less than n elements).

Lemark
  • 139
  • 3
  • 11