Skip to main content
  1. About
  2. For Teams
Asked
Modified 7 months ago
Viewed 201 times
1

The task description is:

I have an array of distinct numbers from 1 to n, for example arr = [5, 3, 4, 1, 2]

Initialize a variable called order to 1, now run through the arr from left to right and look for element that matches with variable order, if found increment order and move forward. In other words we can say Initialize a variable called order to 1 so first go through array from left to right and see where 1 appears in array, then increment order to 2, then move forward in array and look for 2 , if found increment order to 3. Iterating from left to right like above is called an operation

for when arr = [5,3,4,1,2], in one pass from left to right, order changes its value from 1 to 2 when arr[3] is found and then 2 to 3 when arr[4] is found

Repeat above steps until the variable order reaches value n. Number of repetitions is called operations.

So when arr [ 5,3,4,1,2], minimum number of operations required is 3

import java.util.*;

class Main {
    public static int solve(List<Integer> arr) {
        int n = arr.size();
        int order = 0; // Number of sorted items found
        int operations = 0;  // Count of full array scan
        
        while (sortedCount < n) {
            order++;
            for (int i = 0; i < n; i++) {
                if (arr.get(i) == order + 1) {
                    order++;
                }
            }
        }        
        return operations;
    }

    public static void main(String[] args) {
        System.out.println(solve(Arrays.asList(5, 3, 4, 1, 2))); // Output: 3
        System.out.println(solve(Arrays.asList(3,1,4,2,5))); // Output: 2
        System.out.println(solve(Arrays.asList(1,2,3,4))); // Output: 1
        System.out.println(solve(Arrays.asList(2,1))); // Output: 2
    }
}

My code works in time O(n^2), how can we solve this in less time complexity

10
  • 1
    Another thing in your question is you are not incrementing operations; I think maybe you intended the loop to be like this? int operations = 0; while (sortedCount < n) { operations++;
    Robert Silver
    –  Robert Silver
    2025-03-06 21:08:59 +00:00
    Commented Mar 6 at 21:08
  • So, what you want to do is to find the index of the last element that is in monotonically decreasing value. This you can do in one pass through the array. It is trivial.
    ravenspoint
    –  ravenspoint
    2025-03-06 21:23:17 +00:00
    Commented Mar 6 at 21:23
  • actually, posted code should not compile ... sortedCount is never declared
    user85421
    –  user85421
    2025-03-06 21:25:01 +00:00
    Commented Mar 6 at 21:25
  • 1
    @ravenspoint - What would "the last element that is in monotonically decreasing value" for the example array (arr = [5, 3, 4, 1, 2]) be? And for [2,1] (last example in code?)
    user85421
    –  user85421
    2025-03-06 21:35:39 +00:00
    Commented Mar 6 at 21:35
  • After long deep thought, I am sharing my feedback. I dont think its possible to reduce the time complexity further because there is no other data structure allowed. The inner loop must always be present because every element needs to be checked. If the arrays were sorted or if we get to choose other data structure, maybe we can think through. Just my 2 cents.
    Ranadip Dutta
    –  Ranadip Dutta
    2025-03-06 21:36:48 +00:00
    Commented Mar 6 at 21:36

2 Answers 2

10

The following algorithm solves the problem in O(n):

public static int solve(List<Integer> arr) {
    int operations = 0;
    Set<Integer> visited = new HashSet<>();
    for (int i : arr) {
        if (!visited.contains(i - 1))
           operations++;
        visited.add(i);
    }
    return operations;
}

The idea is that if you haven't seen the number - 1 before then you have to get it the next pass, so this is counting all required passes. You could use a boolean array instead of the hash set to be more performant, but it's the same complexity.

Sign up to request clarification or add additional context in comments.

2 Comments

Jean-Baptiste Yunès
HashSet.contains() may decay to O(log n) complexity. At least in theory, that algorithm is not On() but O(n.log n). All of this depends on the hashCode() function.
@Jean-BaptisteYunès I learned that it is amortized O(n). I assume the hash function of primitive types (also boxed) is implemented intelligently. It also not just depends on the hashCode() function, it also depends on the logic used to increase the hash set's capacity and rehashing (which can be avoided here by specifying the capacity on construction). Just used hash set here because it is a little bit more readable than array.
1

here is my idea

    public static int solve(List<Integer> arr) {
        int n = arr.size();
        Map<Integer, Integer> indexMap = new HashMap<>();
        
       
        for (int i = 0; i < n; i++) {
            indexMap.put(arr.get(i), i);
        }
        // we store
        //5 -> 0  
        //3 -> 1  
        //4 -> 2  
        //1 -> 3  
        //2 -> 4  
        
        int operations = 1; //we start from 1
        for (int i = 2; i <= n; i++) { // and try to find each next number (2, 3, 4, ...).
            //If index of i is bigger than index of (i - 1), we’re still good, Numbers are appearing in increasing order
            if (indexMap.get(i) < indexMap.get(i - 1)) {
                operations++; //BUT if index of i is smaller, that means we gotta restart our search (new operation needed).
            }
        }
        //One loop to build the map (O(n))
        //One loop to count operations (O(n))
        // => Total: O(n)
        return operations;
    }


Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

Morty Proxy This is a proxified and sanitized view of the page, visit original site.