简体   繁体   中英

Count the number of times going through a list from beginning

I am trying to solve problem A (called Task Management) in the following website: http://codeforces.com/gym/101439/attachments/download/5742/2017-yandexalgorithm-qualification-round-en.pdf

Basically, we are given a unsorted list of integers from 1 to n and we want to visit integers in order(ie from 1,2,3,4,5,.... n). How many times do we have to go to the beginning of the list until we have visited all integers from 1 to n in increasing order.

Let's say we have a list like: 3 2 1. during the first run through the list we visit only the number 1, during the second run through the list, we visit only the number 2, and during the third run we finally visit the number 3. So we have to go through the list 3 times.

Here is my code:

import java.util.Scanner;
import java.util.ArrayList;


class TaskManagement{

// arr: array of tasks
static int countNumberOfLoops(ArrayList<Integer> arr){
    int targetTask = 1;
    // Last task to close
    int finalTask = arr.size();
    int index=0;
    int count =0;

    while(targetTask != finalTask+1){
        if(index%arr.size()==0) count++;
        if(arr.get(index%arr.size())==targetTask) targetTask++;
        index++;
    }
    System.out.println(count);
    return count;
}

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    int n = scan.nextInt();
    // make a static array of size n
    ArrayList<Integer> arr = new ArrayList<Integer>();

    for (int i=0; i<n; i++) {
        int item = scan.nextInt();
        arr.add(item);
    }

    countNumberOfLoops(arr);
}
}

The problem is: my code is not efficient enough, O(n^2) and for a very large data set, it will be slow.

Is there any way I can implement the code in a more efficient way?

An editorial has been posted here :

Consider a solution with the complexity O(n^2). Use a variable to track the last closed task and go through the list of tasks from the beginning to the end. Increase the counter when passing through the element corresponding to the next task. The constraints are quite large, so this solution doesn't fit the timelimit.

What is the case when we can not find any suitable tasks up to the end of the list? There is only one case: the task number (x + 1) is closer to the beginning of the list then the closed task number x. Therefore, to solve the problem we can determine position of each task in the task list and count the number of distinct numbers x such that the position of task number (x + 1) is less than the position of task number x.

Don't forget to consider the first pass through the task list. The final complexity of the solution is O(n).

  1. Loop through all the numbers and store the index of their occurrence in a hash table or a normal array since numbers are between 1-n. For example if, the numbers were 3, 4, 5, 2, 1 which would result in hash like this. (let's call this Index)

    { 1 -> 4, 2 -> 3, 3 -> 0, 4 -> 1, 5 -> 2 }

  2. Loop from 1 to n-1 and find the index for ith and (i+1)th element.

loopCount = 0;

loopCount = 0;
for (int i=1; i<n; i++) {
    if (Index[i] > Index[i+1]) {
        loopCount++;
    }
}

Time complexity O(n)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM