-2

We are given an array of int which are not sorted (Do not assume that the array contain only positive integer and no duplicate elements.). Each time, we are only allowed to pick a random element and put it at the end of the array. What is the minimum steps required to make this array a sorted list (in ascending order)?

A illustrating example for you to understand

Suppose the given list is {2, 1, 4, 3}, then the minimum step required is 3.

step 1: pick 2, put it at the end of the array, now the array is {1, 4, 3, 2}

step 2: pick 3, put it at the end of the array, now the array is {1, 4, 2, 3}

step 3: pick 4, put it at the end of the array, now the array is {1, 2, 3, 4}

I have tried to solve this problem on my own. But I am not sure if my solution has minimum time complexity and space complexity.

My solutions

suppose the given array is nums, which is a vector of int. My solution is (now with complete code to run it on your own)

#include <vector>
#include <iostream>

using namespace std;

int main(){
    
    int N; // N is the number of elements in this array
    cin >> N;
    vector<int> nums(N);
    vector<int> nums_copy(N);
    for (int i = 0; i != N; ++i){
        cin >> nums[i];
        nums_copy[i] = nums[i];
    }
    sort(nums_copy.begin(), nums_copy.end());

    size_t j = 0;
    for (size_t i = 0, end = nums.size(); i != end; ++i){
        if (nums[i] == nums_copy[j])
            ++j;
    }

    cout << nums.size() - j << endl;
    return 0;
}

The idea is to sort the original array, and then count the number of element in the original array which are in correct order in the sorted array(j in the above code). So the minimum steps required is just nums.size()-j.

The space complexity is O(n) and time complexity is O(nlog(n)) which is just the time complexity of sorting the array.

If you think that my solution is wrong or you have a better solution in term of either time or space complexity or both, share your solution.

Community
  • 1
  • 1
jdhao
  • 13,374
  • 7
  • 87
  • 151
  • @jdhao, your question is ok, but a bit hard to understand. Modify second line to say at each step instead of each time. – Shihab Shahriar Khan Oct 21 '17 at 14:48
  • How is this a programming problem? Looks more like maths/computer science to me. – melpomene Oct 21 '17 at 14:49
  • This is a pretty good algorithmic problem, why should it not be about programming? – Shihab Shahriar Khan Oct 21 '17 at 14:49
  • "efficient" means its time and space complexity is low. – jdhao Oct 21 '17 at 14:57
  • ```I have tried to solve this problem on my own. But I am not sure if my solution is correct or efficient.``` What do you mean? Efficient? You did not give any info on how to obtained this. What should be efficient and what is efficient (and if you answer time and space; there is a trade-off)? Correct? Well you got a solution of 3; brute-forcing all 16 2steps solutions is easy. – sascha Oct 21 '17 at 15:03
  • @sascha, then give your 2 step solution, you can get a sorted list in 2 steps for the given example? – jdhao Oct 21 '17 at 15:10
  • 1
    You misunderstood a lot of comments... especially those explaining why this is a bad question. Expect it to be closed. – sascha Oct 21 '17 at 15:11
  • @sascha I think this is valid algorithm question, I still do not understand why it is downvoted. – jdhao Oct 21 '17 at 15:12
  • 1
    For me it's simple: looks like homework / competition-problem; you talk about your solution-algorithm and want to know if there is something better (without formally defining what is better). You did not present your solution-algorithm, only an example solution. Too broad and missing investment! – sascha Oct 21 '17 at 15:13
  • Better add a high-level description too. And for your task: google something like *minimum/minimize move-to-front operations* (symmetry). – sascha Oct 21 '17 at 15:15
  • @sascha, this is not a homework question, I came across it in a programming site. For experienced programmer, it may seems easy. But for me, it is not. I have googled it. But since I am not a native speaker, so I can not find useful content. That is the reason I asked this question here. – jdhao Oct 21 '17 at 15:29
  • But the solution is 2 :-) (no need to run it) – sascha Oct 21 '17 at 15:34
  • @sascha, how can you get a sorted array from `{2, 1, 4, 3}` in 2 steps, enlighten me, please – jdhao Oct 21 '17 at 15:36
  • I gave some other example (where 2 is enough, your algorithm gives 3). If you want an answer for the general-case, it's a completely different problem not described greatly in your question. So if it's about all cases: there is an O(1) / O(1) answer hidden in the comments. ... i really think this is going nowhere... – sascha Oct 21 '17 at 15:39
  • @sascha, for {3, 1, 2, 4}, my solution will output `2`, have you really run it? – jdhao Oct 21 '17 at 15:41
  • @sascha, show your `O(1)` time complexity algorithm to amaze me, I would like to see such an algorithm – jdhao Oct 21 '17 at 15:51
  • It still depends on what the question is: specific-case vs. general/worst-case... As you did not clarify this, there is nothing to do. – sascha Oct 21 '17 at 15:58
  • 1
    @sascha, I mean the general case. Of course, if the array is sorted, you do not need to perform any operation. you say that you have a `O(1)` time complexity algorithm. What do you mean? – jdhao Oct 21 '17 at 15:59
  • You [should not `#include `](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h), by the way. – melpomene Oct 21 '17 at 16:03
  • @melpomene if you call sort, you are swapping – Beached Oct 21 '17 at 17:09
  • @Beached I'm not calling sort. – melpomene Oct 21 '17 at 17:11
  • @Beached That's the "meta algorithm" for finding how many steps the other algorithm would take. – melpomene Oct 21 '17 at 17:19
  • **Moderator Note:** Comments are not for extended discussion or debugging sessions. I had to delete a bunch of noisy comments here. If you have an answer, then post an answer. If you just want to chat, use [chat]. – Cody Gray Oct 22 '17 at 11:47
  • @sascha, after all this time, you still do not give any valid answer of yours, shame on you. – jdhao Oct 26 '17 at 15:32

2 Answers2

2

I have code that only needs O(1) space and O(n) time:

#include <iostream>
#include <vector>
#include <climits>

static std::size_t xsteps(const std::vector<int> &nums) {
    int min = nums.end()[-1], bad_min = INT_MAX;
    for (std::size_t i = nums.size(); i--; ) {
        if (nums[i] < min) {
            min = nums[i];
        } else if (min < nums[i] && nums[i] < bad_min) {
            bad_min = nums[i];
        }
    }

    std::size_t count = 0;
    std::size_t i;
    for (i = 0; i < nums.size(); i++) {
        if (nums[i] >= bad_min) {
            count++;
        }
    }
    while (i-- && nums[i] >= bad_min) {
        if (nums[i] == bad_min) {
            count--;
        }
    }

    return count;
}

int main() {
    std::cout << xsteps({2, 1, 4, 3}) << '\n';
}

The idea is to first find the smallest element that's out of place (i.e. has a smaller element to the right of it). This is done by the first loop, which iterates from the end, keeping track of the smallest element seen so far (min) and the smallest element that's out of place (bad_min).

By the end of this loop, we know that all elements smaller than bad_min are already in their right place and we don't need to touch them.

Then we iterate over the vector again. We count all elements that are greater than or equal to bad_min as out of place. However, this overestimates the true count: All copies of bad_min that are not themselves out of place (i.e. are not followed by a smaller element) do not need to be moved.

This is fixed in the third loop. It iterates from the right and decrements the counter for each bad_min found, stopping as soon as it sees a smaller element.

melpomene
  • 79,257
  • 6
  • 70
  • 127
-1
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int calcsort(vector<int>& nums)
{
    int start=1;
    for(int i=0;i<nums.size();i++)
    {
        if (nums[i]==start)
            start++;
    }
    return (nums.size()-(start-1));
}
int main()
{
    vector<int> nums={2,1,4,3};
    cout<<calcsort(nums)<<endl;
}

The idea is to find max ascending subsequenсe. Apparently, min amount of steps = nums.size() - subsequenсe's length. That's all.

  • I am asking for a general solution, your solution only targets the specific example given... – jdhao Oct 23 '17 at 12:15
  • int calcsort(vector ) - general solution. main() - check specific example. – Andrej Shirinkin Oct 23 '17 at 12:18
  • You are assuming that the array starts from 1 and each number appears once, which is not implied. For example, try `{2, 1, 2, 3, 4}`, the solution is `3`, but your algorithm gives `1`. – jdhao Oct 23 '17 at 12:23
  • you are right, my fault. but, i think you should add this issue (possibility of duplicates) in description... – Andrej Shirinkin Oct 23 '17 at 12:37