Puzzle: Find the order of n persons standing in a line (based on their heights)

前端 未结 11 2189
抹茶落季
抹茶落季 2020-12-30 05:58

Saw this question on Careercup.com:

Given heights of n persons standing in a line and a list of numbers corresponding to each person (p) that gives the number of pers

11条回答
  •  长发绾君心
    2020-12-30 06:37

    There exists an algorithm with O(nlogn) average complexity, however worst case complexity is still O(n²).

    To achieve this you can use a variation of a binary tree. The idea is, in this tree, each node corresponds to a person and each node keeps track of how many people are in front of him (which is the size of the left subtree) as nodes are inserted.

    Start iterating the persons array in decreasing height order and insert each person into the tree starting from the root. Insertion is as follows:

    1. Compare the frontCount of the person with the current node's (root at the beginning) value.
    2. If it is smaller than it insert the node to the left with value 1. Increase the current node's value by 1.
    3. Else, descend to the right by decreasing the person's frontCount by current node's value. This enables the node to be placed in the correct location.

    After all nodes finished, an inorder traversal gives the correct order of people.

    Let the code speak for itself:

    public static void arrange(int[] heights, int[] frontCounts) {
      Person[] persons = new Person[heights.length];
    
      for (int i = 0; i < persons.length; i++)
        persons[i] = new Person(heights[i], frontCounts[i]);
    
      Arrays.sort(persons, (p1, p2) -> {
        return Integer.compare(p2.height, p1.height);
      });
    
      Node root = new Node(persons[0]);
    
      for (int i = 1; i < persons.length; i++) {
        insert(root, persons[i]);
      }
    
      inOrderPrint(root);
    }
    
    
    private static void insert(Node root, Person p) {
      insert(root, p, p.frontCount);
    }
    
    private static void insert(Node root, Person p, int value) {
      if (value < root.value) { // should insert to the left
        if (root.left == null) {
          root.left = new Node(p);
        } else {
          insert(root.left, p, value);
        }
        root.value++; // Increase the current node value while descending left!
      } else { // insert to the right
        if (root.right == null) {
          root.right = new Node(p);
        } else {
          insert(root.right, p, value - root.value);
        }
      }
    }
    
    private static void inOrderPrint(Node root) {
      if (root == null)
        return;
    
      inOrderPrint(root.left);
    
      System.out.print(root.person.height);
    
      inOrderPrint(root.right);
    }
    
    private static class Node {
      Node left, right;
      int value;
      public final Person person;
    
      public Node(Person person) {
        this.value = 1;
        this.person = person;
      }
    }
    
    private static class Person {
      public final int height;
      public final int frontCount;
    
      Person(int height, int frontCount) {
        this.height = height;
        this.frontCount = frontCount;
      }
    }
    
    public static void main(String[] args) {
      int[] heights = {5, 3, 2, 6, 1, 4};
      int[] frontCounts = {0, 1, 2, 0, 3, 2};
    
      arrange(heights, frontCounts);
    }
    

提交回复
热议问题