Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if an int array is a circularly sorted array?

I have an integer array, say {1, 3, 4, 7, -9, 0}. This array is circularly sorted, while the array {2, 4, 9 , 3} is not circularly sorted.

An array is circularly sorted if its elements are sorted except for a rotation.

For example:

4 5 6 7 1 2 3

The elements here, 1 2 3 4 5 6 7, are "in order", but they are rotated to the left by three. So if we rotate to the right by 3 we get 1 2 3 4 5 6 7 which is a sorted array.

Given an array, how can you check whether the array is a circularly sorted?

like image 552
Khuong Avatar asked Jun 27 '15 02:06

Khuong


People also ask

What is a circularly sorted array?

Circularly sorted arrays are arrays that are sorted in ascending or descending order and then rotated by a number of steps.

How do you check array is rotated and sorted?

Take Input of an array element. A Boolean function checkSortedandRotated(int *arr, int n) takes an array and its size as the input and returns true if the array is sorted and rotated otherwise false. Iterate over the whole array and count the number of elements which are (arr[i] > arr[i+1]%n).

What is the best way to search for a number in a rotated sorted array and the time complexity for the same?

The idea is to find the pivot point, divide the array into two sub-arrays and perform a binary search. For a sorted (in increasing order) and rotated array, the pivot element is the only element for which the next element to it is smaller than it. Using binary search based on the above idea, pivot can be found.


3 Answers

You can loop through the array and check that all values are increasing. And as soon as you hit the first value that is not increasing, check that it and all of the following values are increasing AND less than or equal to the first element in the array.

Edit:

I feel that people are discounting Daniel's solution because they don't understand it or think it is broken. This is sad because I think his solution is brilliant.

def is_circular_sorted(arr):
    count = 0
    length = len(arr)
    for i in range(length):
        if arr[i] > arr[(i+1) % len(arr)]:
            count += 1
    return count <= 1

In [4]: is_circular_sorted([1, 2, 3, 4])
Out[4]: True

In [5]: is_circular_sorted([1, 1, 1, 1])
Out[5]: True

In [6]: is_circular_sorted([1, 3, 4, 7, -9])
Out[6]: True

In [7]: is_circular_sorted([1, 3, 4, 2])
Out[7]: False

For a little bit of explanation. To check if a list is circular-sorted, my original answer said you needed to check there was one or less "break" from being completely sorted AND all of the numbers after the "break" were less than the first number in the array.

However as Daniel's answer shows, you don't need to check ALL numbers after the "break", only the last number (which also happens to be the biggest/maximum number after the break because they are sorted).

There should always be one break, unless the list is filled with the same numbers in which case there would be no breaks and count would be 0.

like image 97
Samuel O'Malley Avatar answered Sep 22 '22 04:09

Samuel O'Malley


In case some of the users wonder how the implementation looks like.

public boolean isCircularSorted(int[] array)
{
    int size = array.length;
    int count = 0;

    for(int x=0; x<size; x++)
        if(array[x] > array[(x+1)%size])
            count ++;
    return (count <= 1);
}

This was also mentioned by user Daniel.

like image 34
user3437460 Avatar answered Sep 18 '22 04:09

user3437460


As @Daniel said, using value[i] > value[(i+1)%length], if it true we count up 1, if the count at the end equals to 0 or 1, the original array is circularly sorted array! I think it is a good way!!

like image 42
Khuong Avatar answered Sep 21 '22 04:09

Khuong