Algorithm for finding the order in which tasks are set to start time and duration

I recently visited an interview in which I was asked this question:

The specified start time in the array: [1, 2, 3, 2] and their duration[3, 4, 4, 3]

Find and return the order of the task. For this example, the end time is:, [4, 6, 7, 5]so the return value should be [1, 3, 4, 2].

My approach / solution:

Create a data structure that represents each class as a Task object that has the following attributes:

  • Start time
  • End time
  • Duration
  • End index

Then sort the array by the end time of each object. Compare each element with the original index of the array and return the completion index to the original task order.

. ( ). , . = .

+4
6

>

:

: [4, 6, 7, 5]

: [0,1,2,3]

( , , = 10 ), , , .

, .

0

, (, ), (, ):

create collection first[] with elements (starttime, duration)
first.append (1, 3)
first.append (2, 4)
first.append (3, 4)
first.append (2, 3)

(starttime, duration) first = [(1,3), (2,4), (3,4), (2,3)].

, , , :

  • .
  • .

second, first, :

create array second[] with elements (firstindex, endtime)
for each index in first.indexes:
    second.append (index, first[index].starttime + first[index].duration)

(firstindex, endtime) tuples second = [(1,4), (2,6), (3,7), (4,5)] ( , , ).

second , second = [(1,4), (4,5), (2,6), (3,7)].

:

for each index in second.indexes:
    output "task # ", second[index].firstindex
    output " starts at, " first[second[index].firstindex].starttime
    output " duration, " first[second[index].firstindex].duration
    output " ends at ", second[index].endtime, new-line

:

task # 1 starts at 1 duration 3 ends at 4
task # 4 starts at 2 duration 3 ends at 5
task # 2 starts at 2 duration 4 ends at 6
task # 3 starts at 3 duration 4 ends at 7
+1

: , -

, . , , , , , O(n log n), .

, , , , O(n log n).

, O(n log n), . , , , , , , .

, .

+1

, , .

Java:

int[] getCompletionOrder(int[] startTimes, int[] durations) {
  // Check that startTimes.length == durations.length.
  Integer[] indexes = new Integer[startTimes.length];
  for (int i = 0; i < indexes.length; ++i) {
    indexes[i] = i;
  }
  Arrays.sort(indexes, new Comparator<Integer, Integer>() {
    @Override public int compare(Integer a, Integer b) {
      return Integer.compare(
          startTimes[a] + durations[a],
          startTimes[b] + durations[b]);
    }
  });
  int[] result = new int[startTimes.length];
  for (int i = 0; i < result.length; ++i) {
    // In your question, your task indexes are 1-based, for some reason.
    result[i] = indexes[i] + 1;
  }
  return result;
}
0

, , . , .

, (. ), .

, , .

:

public class Task {

      private String m_name;
      private double m_startTime;
      private double m_duration;

      ...

      public double calculateEndTime() {
            return m_startTime + m_duration;
      }
}

TaskComparator:

public class TaskComparator implements Comparator<Task>{
    @Override
    public int compare(Task t1, Task t2) {
        if (t1 == null || t2 == null) {
            return 0;
        }
    return Double.compare(t1.calculateEndTime(), t2.calculateEndTime());
}

:

public void go() {
    List<Task> tasks = new ArrayList<Task>();
    tasks.add(new Task("First Task", 1, 3));
    tasks.add(new Task("Second Task", 2, 4));
    tasks.add(new Task("Third Task", 3, 4));
    tasks.add(new Task("Fourth Task", 2, 3));
    Collections.sort(tasks, new TaskComparator());
    for (Task task : tasks) {
        System.out.println(task.toString());
    }
}
0

Glubus , , . , :

  • int[] calculateCompletionsOrder(int[] starttimes, int[] durations) {
    
        // the key is the endtime (sorted ascending), the value is a list of the taskid with corresponding endtime  
        TreeMap<Integer, List<Integer>> set = new TreeMap<Integer, List<Integer>>();
    
        // first iteration is needed to calucate endtimes
        for (int taskId = 0; taskId < starttimes.length; taskId++) { // time complexity O(nlogn)
            // calculate end time for the current task
            int endtime = starttimes[taskId] + durations[taskId];
            // add the task to the list of task with same end time
            List<Integer> taskIds = set.get(endtime); // time complexity O(logn)
            if (taskIds == null) {
                taskIds = new ArrayList<Integer>();
                set.put(endtime, taskIds); // time complexity O(logn)
            }
            taskIds.add(taskId); // time complexity O(1)
        }
    
        // now calculate the order each task get completed
        int[] completionorders = new int[starttimes.length];
        int order = 1;
        // iterate over end times in ascending order
        for (List<Integer> taskIds : set.values()) { // time complexity O(n)
            for (int taskId : taskIds) {
                // set the completion order for the selected task
                completionorders[taskId] = order;
            }
            // increment order for next group of tasks with next end time 
            order++;
        }
    
        return completionorders;
    }
    

. - , , O (nlogn).

: " ".

, . : " , 1 4".

, (..., -3, -2, -1, 0, 1, 2, 3,...). "" , .

  • Input:

    • : [1, 2, 3, 2]
    • : [3, 4, 4, 3]
  • ( ):

    max-end-time = 0;
    for (int i = 0; i < start-time.length; ++i) {
       end-time[i] = start-time[i] + durations[i];
       max-end-time = max-end-time > end-time[i] ? max-end-time : end-time[i];
    }
    
  • :

    • end-time: [4, 6, 7, 5]
    • max-end-time: 7
  • ( ):

    for (int i = 0; i < end-time.length; ++i) {
       order[i] = end-time[i] - max-end-time;           
    }
    

At the end of the second phase, your array of end order: [-3, -1, 0, -2].

So, task 0 is the first, task 2 is the third, task 3 is the fourth, task 4 is the second or other form: [1, 3, 4, 2].

Complexity: if n is the task number, the algorithm performs n + n = 2n iterations. So this algorithm is O (n).

0
source

All Articles