Related
I have been checking it over the net and asking friends, since I am very new to coding. I find all these posts about writing all possible permutations on n letters. I am not looking for that.
What I am trying to achieve is given an array of integers, I want to turn that into a permutation as follows. Say X is an array of integers;
X= { 3, 4, 1, 2, 5}
Now people familiar with permutation groups (or symmetric group) would know that there is cycle notation for any permutation. I want to see X as some function that assigns values as follow;
1 --> 3
2 --> 4
3 --> 1
4 --> 2
5 --> 5
In a way, if the above function is the permutation sigma, then we have sigma(1)= 1st entry in X, sigma(2)= 2nd entry in X and so on.
And finally, I need to count how many loops there will be in this permutation, or number of cycles in a cycle notation. Again for the example above, we have
1 --> 3 --> 1 (So this is a one loop)
2 --> 4 --> 2 (Another loop)
5 --> 5 (This is also a loop)
So it should also tell me that X has 3 loops in this case.
This might be a detailed question, but any any, tiny bit of help is appreciated. Thank you all sooo much!
The array of integers already is a permutation, only offset by one, since arrays in C are zero-indexed. You can iterate through that array/permutation p in a loop; once you see an element x that does not belong to any known cycle, continuously calculate p[x], p[p[x]], ... until you get back to x (subtract 1 when doing that in the C code to account for the zero indexing of C arrays). That is one cycle; account for this cycle and proceed to the next element. C code is presented below.
Another way is to convert the permutation to a graph and count the number of connected components in the graph, as done here.
#include <stdio.h>
#include <stdbool.h>
unsigned count_cycles(const unsigned permutation[], const unsigned n)
{
unsigned num_cycles = 0;
bool visited[n];
unsigned i;
// initially, no elements are visited
for(i = 0; i < n; ++i) {
visited[i] = false;
}
// iterate through all elements
for(i = 0; i < n; ++i) {
if(!visited[i]) {
// found a new cycle; mark all elements in it as visited
int x = i;
do {
visited[x] = true;
x = permutation[x] - 1;
} while(!visited[x]);
// account for the new cycle
num_cycles++;
}
}
return num_cycles;
}
int main()
{
const unsigned permutation[] = { 3, 4, 1, 2, 5};
const unsigned N = 5;
printf("%u\n", count_cycles(permutation, N)); // prints "3"
}
I have been learning memory allocation and pointers lately, and I made this program which will ask the user to input the dimensions of a matrix and enter it's elements, after which it displays the elements in a matrix format. Here's the code that I've typed.
#include"stdio.h"
#include"stdlib.h"
int *minput();
int *minput(int x,int y)
{
int *M;
M=(int*)malloc(x*y*sizeof(int));
for(int i=0;i<=(x-1);i++)
{
for(int j=0;j<=(y-1);j++)
{
printf("A(%d,%d)=",i+1,j+1);
scanf("%d",(M+i+j));
}
}
return M;
}
int main()
{
int *A,a,b;
printf("Matrix is (m*n)\n\n");
printf("m=");
scanf("%d",&a);
printf("n=");
scanf("%d",&b);
A=minput(a,b);
printf("\n");
for(int k=0;k<=(a-1);k++)
{
for(int l=0;l<=(b-1);l++)
{
printf("%d ",*(A+k+l));
}
printf("\n");
}
free(A);
return 0;
}
However when I gave my inputs, I got this:
Matrix is (m*n)
m=3
n=3
A(1,1)=1
A(1,2)=2
A(1,3)=3
A(2,1)=4
A(2,2)=5
A(2,3)=6
A(3,1)=7
A(3,2)=8
A(3,3)=9
1 4 7
4 7 8
7 8 9
What's wrong? Amn't I supposed to get
1 2 3
4 5 6
7 8 9
Is there anything I had made wrong in my code?
You get incorrect output because *(A+k+l) is not the right way of accessing matrix element at matrix[k][l].
For addressing a matrix stored as a "flat" array you need to multiply the value of one of the indexes by the size of the opposite dimension. Depending on which index you multiply you get either a row-major order or a column-major order.
You need to apply the same fix to (M+i+j) inside minput function.
// Input
scanf("%d",(M+y*i+j));
...
// Output
printf("%d ",*(A+b*k+l));
The idea behind multiplying k by b is to make k "count faster". For each increment of k by 1 you need to skip an entire row of b elements. In your three-column matrix example, if you would like to access elements at A[k][0] (the initial column) of your matrix for each row, your index would count by three: 0, 3, 6. This is accomplished by multiplying k by b. The rest is the same as the usual pointer arithmetic: *(A+b*k+l) is equivalent to A[b*k+l].
Demo.
Lets take a close look at one of your loops (I use the input loop, but the error is in the output loop as well):
for(int i=0;i<=(x-1);i++)
{
for(int j=0;j<=(y-1);j++)
{
printf("A(%d,%d)=",i+1,j+1);
scanf("%d",(M+i+j));
}
}
The first iteration of the outer loop, i is zero. Then the inner loop runs, and we read into (in turn) M+0+0, M+0+1 and M+0+2.
Then we run the second iteration of the outer loop, where the inner loop will read into M+1+0, M+1+1 and M+1+2.
In these two iterations of the outer loop you will read into M+1 and M+2 twice. That's because M+0+1 and M+1+0 are the same element.
To fix this, lets take a look at your "matrix" as it is in memory
+---+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+---+---+---+---+---+---+---+---+---+
The numbers inside are the indexes. Now, 0, 1 and 2 is the first row. 3, 4 and 5 is the second. And 6, 7 and 8 is the last.
From this we can see that to get to the next line, we have to add the number of columns.
From this we get the formula line * number_of_columns + column to get the index.
Putting it in place, your input loop could look like
for(int i=0;i<x;i++)
{
for(int j=0;j<y;j++)
{
printf("A(%d,%d)=",i+1,j+1);
scanf("%d",M+i*y+j);
}
}
To choose the address in which to write a value, you use:
M+i+j
Let's try that for a few values of (i,j):
0,0 -> M + 0
0,1 -> M + 1
0,2 -> M + 2 // So far so good.
1,0 -> M + 1 // not right
1,1 -> M + 2 // not right
... etc.
You want M + (i * x) + j. For x == 3:
0,0 -> M + 0
0,1 -> M + 1
0,2 -> M + 2
1,0 -> M + 3
1,1 -> M + 4
... etc.
The same goes for the pointer arithmetic when reading from the same memory.
Furthermore, since the pointer just goes up by one each time, you could get the same behaviour with:
int *m = M;
for(int i=0;i<x;i++)
{
for(int j=0;j<=(y-1);j++)
{
printf("A(%d,%d)=",i+1,j+1);
scanf("%d",m);
m++;
}
}
Or even:
for(int i=0; i<x*y; i++) {
printf("A(%d,%d)=", i/3, i%3);
scanf("%d", M + i);
}
Other points:
In one method you use variables x,y,i,j, and in another you use a,b,k,l. I assume you've done this because you don't want to overwrite one with the other. But because of scope, that's not a factor. x is local to the function minput() -- you can have another x in main() and they will be completely independent of one another. Use x,y,i,j in both places, because they are the "sensible" names for dimensions and loop counters.
for(i=0; i<x; i++) is the conventional way of looping x times. Your i<=(x-1) is equivalent but messy and confusing.
Casting the result of malloc() is discouraged nowadays. Do I cast the result of malloc?
int *M = malloc(x*y*sizeof(int));
I want to create a game, which monster is aligned from left to right horizontally, the order of monsters has other logical meaning (e.g.: the appearing sequence), but I want to play some effects which starts from the middle monster
the array, for example, for odd number size array:
int[] a=new int[]{1,2,3,4,5};
the access sequence is 3,2,4,1,5 (or 3,4,2,5,1)
for even number size array:
int[] a=new int[]{1,2,3,4,5,6};
the access sequence is 3,4,2,5,1,6 or (4,3,5,2,6,1)
If it is in something like vector in c++, it will be:
std::vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(4);
a.push_back(5);
while(a.size()>0){
printf("%d\n",a[a.size()/2]);
a.erase(a.begin()+a.size()/2);
}
which the output is
3
4
2
5
1
But I want an algorithm which is suitable to be used in array, which the position of element cannot be changed,
I tried something like:
int a[]={1,2,3,4,5};
for(int i=a.size()/2;i>=0 && i<a.size();i=XXXX){
printf("%d\n",a[i]);
}
which XXXX is the update statement, which I still don't know what should it be.
In fact, I don't know if my init value and condition statement in for loop is correct. I even don't know if it can be done by a single loop.
Ok, I know I can have a temp vector and then copy the index to do that, but I also want to know if it can be done in a single for loop without any temp vector or array.
Can anyone help (or is there another simple algorithm to do that?)?
This is an answer for the edited question that is language-agnostic and wants a single function to display the elements in the stated order.
First, chose a "middle" index.
var i = Math.floor((a.length-1)/2);
Then alternate right and left moving outwards incrementally until either edge of the array is encountered.
To facilitate this, start with a variable d = 0 which will be the distance from the middle element. This d will be updated like so upon each iteration
d += -(2*d) + (d > 0 ? 0 : 1);
with the below update pattern:
0, 1, -1, 2, -2, ...
If the middle index is 2 in array [1,2,3,4,5], then applying a[i + d] will result in
3, 4, 2, 5, 1
I hope this is what you are looking for.
Here is a JavaScript implementation:
var a = [1,2,3,4,5,7,8];
var i = Math.floor((a.length-1)/2);
for (var d = 0; i+d >= 0 && i+d < a.length;) {
// Print out the value
console.log(a[i + d]);
// Outward-moving logic
d += -(2*d) + (d > 0 ? 0 : 1);
}
or if you want this all in the for-loop like you've tried in your question, you can do this:
var a = [1,2,3,4,5,7,8];
var i = Math.floor((a.length-1)/2);
for (var d = 0; i+d >= 0 && i+d < a.length; d += -(2*d) + (d > 0 ? 0 : 1)) {
console.log( a[i + d] ); // print the value
}
Result on [1,2,3,4,5] (odd-length array):
3 4 2 5 1
Result on [1,2,3,4,5,6,7,8] (even-length array):
4 5 3 6 2 7 1 8
Demo: JSBin
An algorithm to list the elements from innermost to outermost is to pull off the last and first entries (pop and shift) in the array in alternation until no elements are left, then reverse the list of what you have pulled off. This works for odd and even-length arrays naturally.
For example,
1,2,3,4,5,6
1,2,3,4,5 6
2,3,4,5 6,1
2,3,4 6,1,5
3,4 6,1,5,2
3 6,1,5,2,4
6,1,5,2,4,3
3,4,2,5,1,6 // Reversed list from above
and
1,2,3,4,5
1,2,3,4 5
2,3,4 5,1
2,3 5,1,4
3 5,1,4,2
5,1,4,2,3
3,2,4,1,5 // Reversed list from above
You can use this above algorithm to create an index map array which you can use to access your main array in the order you requested. For example:
// Start with an array of indices
// from 0..arr.length-1
0,1,2,3,4
0,1,2,3 4
1,2,3 4,0
1,2 4,0,3
2 4,0,3,1
4,0,3,1,2
2,1,3,0,4 // Reversed list from above
Then you have a mapping array
int[] arr = new int[]{1,2,3,4,5};
int[] map = new int[]{2,1,3,0,4};
which you can use to access your main array, for example
arr[map[0]]; // returns 3
Edit: Added Java implementation and demo.
public static int[] creatIndexMap(int length) {
// Create a deque so elements can be removed from both ends
Deque<Integer> tmp = new LinkedList<Integer>();
for(int i = 0; i < length; i++) {
tmp.add(i);
}
// In alternation remove the last and first entries of tmp
// and add them in reverse order to the map array
int[] map = new int[length];
int index = length-1;
while (!tmp.isEmpty()) {
// Remove last element
map[index--] = (int) tmp.removeLast();
// Remove first element
if(!tmp.isEmpty()) {
map[index--] = (int) tmp.removeFirst();
}
}
return map;
}
Demo: IDEOne
It is an interview question. We have an array of integers of size N containing element between 0 to N-1. It may be possible that a number can occur more than two times. The goal is to find pairs that sum to a given number X.
I did it using an auxiliary array having count of elements of primary array and then rearranging primary according auxiliary array so that primary is sorted and then searched for pairs.
But interviewer wanted space complexity constant, so I told him to sort the array but it is nlogn time complexity solution. He wanted O(n) solution.
Is there any method available to do it in O(n) without any extra space?
No, I don't believe so. You either need extra space to be able to "sort" the data in O(n) by assigning to buckets, or you need to sort in-place which will not be O(n).
Of course, there are always tricks if you can make certain assumptions. For example, if N < 64K and your integers are 32 bits wide, you can multiplex the space required for the count array on top of the current array.
In other words, use the lower 16 bits for storing the values in the array and then use the upper 16 bits for your array where you simply store the count of values matching the index.
Let's use a simplified example where N == 8. Hence the array is 8 elements in length and the integers at each element are less than 8, though they're eight bits wide. That means (initially) the top four bits of each element are zero.
0 1 2 3 4 5 6 7 <- index
(0)7 (0)6 (0)2 (0)5 (0)3 (0)3 (0)7 (0)7
The pseudo-code for an O(n) adjustment which stores the count into the upper four bits is:
for idx = 0 to N:
array[array[idx] % 16] += 16 // add 1 to top four bits
By way of example, consider the first index which stores 7. That assignment statement will therefore add 16 to index 7, upping the count of sevens. The modulo operator is to ensure that values which have already been increased only use the lower four bits to specify the array index.
So the array eventually becomes:
0 1 2 3 4 5 6 7 <- index
(0)7 (0)6 (1)2 (2)5 (0)3 (1)3 (1)7 (3)7
Then you have your new array in constant space and you can just use int (array[X] / 16) to get the count of how many X values there were.
But, that's pretty devious and requires certain assumptions as mentioned before. It may well be that level of deviousness the interviewer was looking for, or they may just want to see how a prospective employee handle the Kobayashi Maru of coding :-)
Once you have the counts, it's a simple matter to find pairs that sum to a given X, still in O(N). The basic approach would be to get the cartestian product. For example, again consider that N is 8 and you want pairs that sum to 8. Ignore the lower half of the multiplexed array above (since you're only interested in the counts, you have:
0 1 2 3 4 5 6 7 <- index
(0) (0) (1) (2) (0) (1) (1) (3)
What you basically do is step through the array one by one getting the product of the counts of numbers that sum to 8.
For 0, you would need to add 8 (which doesn't exist).
For 1, you need to add 7. The product of the counts is 0 x 3, so that gives nothing.
For 2, you need to add 6. The product of the counts is 1 x 1, so that gives one occurrence of (2,6).
For 3, you need to add 5. The product of the counts is 2 x 1, so that gives two occurrences of (3,5).
For 4, it's a special case since you can't use the product. In this case it doesn't matter since there are no 4s but, if there was one, that couldn't become a pair. Where the numbers you're pairing are the same, the formula is (assuming there are m of them) 1 + 2 + 3 + ... + m-1. With a bit of mathematical widardry, that turns out to be m(m-1)/2.
Beyond that, you're pairing with values to the left, which you've already done so you stop.
So what you have ended up with from
a b c d e f g h <- identifiers
7 6 2 5 3 3 7 7
is:
(2,6) (3,5) (3,5)
(c,b) (e,d) (f,d) <- identifiers
No other values add up to 8.
The following program illustrates this in operation:
#include <stdio.h>
int arr[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 4, 4, 4, 4};
#define SZ (sizeof(arr) / sizeof(*arr))
static void dumpArr (char *desc) {
int i;
printf ("%s:\n Indexes:", desc);
for (i = 0; i < SZ; i++) printf (" %2d", i);
printf ("\n Counts :");
for (i = 0; i < SZ; i++) printf (" %2d", arr[i] / 100);
printf ("\n Values :");
for (i = 0; i < SZ; i++) printf (" %2d", arr[i] % 100);
puts ("\n=====\n");
}
That bit above is just for debugging. The actual code to do the bucket sort is below:
int main (void) {
int i, j, find, prod;
dumpArr ("Initial");
// Sort array in O(1) - bucket sort.
for (i = 0; i < SZ; i++) {
arr[arr[i] % 100] += 100;
}
And we finish with the code to do the pairings:
dumpArr ("After bucket sort");
// Now do pairings.
find = 8;
for (i = 0, j = find - i; i <= j; i++, j--) {
if (i == j) {
prod = (arr[i]/100) * (arr[i]/100-1) / 2;
if (prod > 0) {
printf ("(%d,%d) %d time(s)\n", i, j, prod);
}
} else {
if ((j >= 0) && (j < SZ)) {
prod = (arr[i]/100) * (arr[j]/100);
if (prod > 0) {
printf ("(%d,%d) %d time(s)\n", i, j, prod);
}
}
}
}
return 0;
}
The output is:
Initial:
Indexes: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Counts : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Values : 3 1 4 1 5 9 2 6 5 3 5 8 9 4 4 4 4
=====
After bucket sort:
Indexes: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Counts : 0 2 1 2 5 3 1 0 1 2 0 0 0 0 0 0 0
Values : 3 1 4 1 5 9 2 6 5 3 5 8 9 4 4 4 4
=====
(2,6) 1 time(s)
(3,5) 6 time(s)
(4,4) 10 time(s)
and, if you examine the input digits, you'll find the pairs are correct.
This may be done by converting the input array to the list of counters "in-place" in O(N) time. Of course this assumes input array is not immutable. There is no need for any additional assumptions about unused bits in each array element.
Start with the following pre-processing: try to move each array's element to the position determined by element's value; move element on this position also to the position determined by its value; continue until:
next element is moved to the position from where this cycle was started,
next element cannot be moved because it is already on the position corresponding to its value (in this case put current element to the position from where this cycle was started).
After pre-processing every element either is located at its "proper" position or "points" to its "proper" position. In case we have an unused bit in each element, we could convert each properly positioned element into a counter, initialize it with "1", and allow each "pointing" element to increase appropriate counter. Additional bit allows to distinguish counters from values. The same thing may be done without any additional bits but with less trivial algorithm.
Count how may values in the array are equal to 0 or 1. If there are any such values, reset them to zero and update counters at positions 0 and/or 1. Set k=2 (size of the array's part that has values less than k replaced by counters). Apply the following procedure for k = 2, 4, 8, ...
Find elements at positions k .. 2k-1 which are at their "proper" position, replace them with counters, initial value is "1".
For any element at positions k .. 2k-1 with values 2 .. k-1 update corresponding counter at positions 2 .. k-1 and reset value to zero.
For any element at positions 0 .. 2k-1 with values k .. 2k-1 update corresponding counter at positions k .. 2k-1 and reset value to zero.
All iterations of this procedure together have O(N) time complexity. At the end the input array is completely converted to the array of counters. The only difficulty here is that up to two counters at positions 0 .. 2k-1 may have values greater than k-1. But this could be mitigated by storing two additional indexes for each of them and processing elements at these indexes as counters instead of values.
After an array of counters is produced, we could just multiply pairs of counters (where corresponding pair of indexes sum to X) to get the required counts of pairs.
String sorting is n log n however if you can assume the numbers are bounded (and you can because you're only interested in numbers that sum to a certain value) you can use a Radix sort. Radix sort takes O(kN) time, where "k" is the length of the key. That's a constant in your case, so I think it's fair to say O(N).
Generally I would however solve this using a hash e.g.
http://41j.com/blog/2012/04/find-items-in-an-array-that-sum-to-15/
Though that is of course not a linear time solution.
Input: A read-only array of N elements containing integer values from 1 to N (some integer values can appear more than once!). And a memory zone of a fixed size (10, 100, 1000 etc - not depending on N).
How to tell in O(n) if the array represents a permutation?
--What I achieved so far (an answer proved that this was not good):--
I use the limited memory area to store the sum and the product of the array.
I compare the sum with N*(N+1)/2 and the product with N!
I know that if condition (2) is true I might have a permutation. I'm wondering if there's a way to prove that condition (2) is sufficient to tell if I have a permutation. So far I haven't figured this out ...
I'm very slightly skeptical that there is a solution. Your problem seems to be very close to one posed several years ago in the mathematical literature, with a summary given here ("The Duplicate Detection Problem", S. Kamal Abdali, 2003) that uses cycle-detection -- the idea being the following:
If there is a duplicate, there exists a number j between 1 and N such that the following would lead to an infinite loop:
x := j;
do
{
x := a[x];
}
while (x != j);
because a permutation consists of one or more subsets S of distinct elements s0, s1, ... sk-1 where sj = a[sj-1] for all j between 1 and k-1, and s0 = a[sk-1], so all elements are involved in cycles -- one of the duplicates would not be part of such a subset.
e.g. if the array = [2, 1, 4, 6, 8, 7, 9, 3, 8]
then the element in bold at position 5 is a duplicate because all the other elements form cycles: { 2 -> 1, 4 -> 6 -> 7 -> 9 -> 8 -> 3}. Whereas the arrays [2, 1, 4, 6, 5, 7, 9, 3, 8] and [2, 1, 4, 6, 3, 7, 9, 5, 8] are valid permutations (with cycles { 2 -> 1, 4 -> 6 -> 7 -> 9 -> 8 -> 3, 5 } and { 2 -> 1, 4 -> 6 -> 7 -> 9 -> 8 -> 5 -> 3 } respectively).
Abdali goes into a way of finding duplicates. Basically the following algorithm (using Floyd's cycle-finding algorithm) works if you happen across one of the duplicates in question:
function is_duplicate(a, N, j)
{
/* assume we've already scanned the array to make sure all elements
are integers between 1 and N */
x1 := j;
x2 := j;
do
{
x1 := a[x1];
x2 := a[x2];
x2 := a[x2];
} while (x1 != x2);
/* stops when it finds a cycle; x2 has gone around it twice,
x1 has gone around it once.
If j is part of that cycle, both will be equal to j. */
return (x1 != j);
}
The difficulty is I'm not sure your problem as stated matches the one in his paper, and I'm also not sure if the method he describes runs in O(N) or uses a fixed amount of space. A potential counterexample is the following array:
[3, 4, 5, 6, 7, 8, 9, 10, ... N-10, N-9, N-8, N-7, N-2, N-5, N-5, N-3, N-5, N-1, N, 1, 2]
which is basically the identity permutation shifted by 2, with the elements [N-6, N-4, and N-2] replaced by [N-2, N-5, N-5]. This has the correct sum (not the correct product, but I reject taking the product as a possible detection method since the space requirements for computing N! with arbitrary precision arithmetic are O(N) which violates the spirit of the "fixed memory space" requirement), and if you try to find cycles, you will get cycles { 3 -> 5 -> 7 -> 9 -> ... N-7 -> N-5 -> N-1 } and { 4 -> 6 -> 8 -> ... N-10 -> N-8 -> N-2 -> N -> 2}. The problem is that there could be up to N cycles, (identity permutation has N cycles) each taking up to O(N) to find a duplicate, and you have to keep track somehow of which cycles have been traced and which have not. I'm skeptical that it is possible to do this in a fixed amount of space. But maybe it is.
This is a heavy enough problem that it's worth asking on mathoverflow.net (despite the fact that most of the time mathoverflow.net is cited on stackoverflow it's for problems which are too easy)
edit: I did ask on mathoverflow, there's some interesting discussion there.
This is impossible to do in O(1) space, at least with a single-scan algorithm.
Proof
Suppose you have processed N/2 of the N elements. Assuming the sequence is a permutation then, given the state of the algorithm, you should be able to figure out the set of N/2 remaining elements. If you can't figure out the remaining elements, then the algorithm can be fooled by repeating some of the old elements.
There are N choose N/2 possible remaining sets. Each of them must be represented by a distinct internal state of the algorithm, because otherwise you couldn't figure out the remaining elements. However, it takes logarithmic space to store X states, so it takes BigTheta(log(N choose N/2)) space to store N choose N/2 states. That values grows with N, and therefore the algorithm's internal state can not fit in O(1) space.
More Formal Proof
You want to create a program P which, given the final N/2 elements and the internal state of the linear-time-constant-space algorithm after it has processed N/2 elements, determines if the entire sequence is a permutation of 1..N. There is no time or space bound on this secondary program.
Assuming P exists we can create a program Q, taking only the internal state of the linear-time-constant-space algorithm, which determines the necessary final N/2 elements of the sequence (if it was a permutation). Q works by passing P every possible final N/2 elements and returning the set for which P returns true.
However, because Q has N choose N/2 possible outputs, it must have at least N choose N/2 possible inputs. That means the internal state of the original algorithm must store at least N choose N/2 states, requiring BigTheta(log N choose N/2), which is greater than constant size.
Therefore the original algorithm, which does have time and space bounds, also can't work correctly if it has constant-size internal state.
[I think this idea can be generalized, but thinking isn't proving.]
Consequences
BigTheta(log(N choose N/2)) is equal to BigTheta(N). Therefore just using a boolean array and ticking values as you encounter them is (probably) space-optimal, and time-optimal too since it takes linear time.
I doubt you would be able to prove that ;)
(1, 2, 4, 4, 4, 5, 7, 9, 9)
I think that more generally, this problem isn't solvable by processing the numbers in order. Suppose you are processing the elements in order and you are halfway the array. Now the state of your program has to somehow reflect which numbers you've encountered so far. This requires at least O(n) bits to store.
This isn't going to work due to the complexity being given as a function of N rather than M, implying that N >> M
This was my shot at it, but for a bloom filter to be useful, you need a big M, at which point you may as well use simple bit toggling for something like integers
http://en.wikipedia.org/wiki/Bloom_filter
For each element in the array
Run the k hash functions
Check for inclusion in the bloom filter
If it is there, there is a probability you've seen the element before
If it isn't, add it
When you are done, you may as well compare it to the results of a 1..N array in order, as that'll only cost you another N.
Now if I haven't put enough caveats in. It isn't 100%, or even close since you specified complexity in N, which implies that N >> M, so fundamentally it won't work as you have specified it.
BTW, the false positive rate for an individual item should be
e = 2^(-m/(n*sqrt(2)))
Which monkeying around with will give you an idea how big M would need to be to be acceptable.
I don't know how to do it in O(N), or even if it can be done in O(N). I know that it can be done in O(N log N) if you (use an appropriate) sort and compare.
That being said, there are many O(N) techniques that can be done to show that one is NOT a permutation of the other.
Check the length. If unequal, obviously not a permutation.
Create an XOR fingerprint. If the value of all the elements XOR'ed together does not match, then it can not be a permutation. A match would however be inconclusive.
Find the sum of all elements. Although the result may overflow, that should not be a worry when matching this 'fingerprint'. If however, you did a checksum that involved multiplying then overflow would be an issue.
Hope this helps.
You might be able to do this in randomized O(n) time and constant space by computing sum(x_i) and product(x_i) modulo a bunch of different randomly chosen constants C of size O(n). This basically gets you around the problem that product(x_i) gets too large.
There's still a lot of open questions, though, like if sum(x_i)=N(N+1)/2 and product(x_i)=N! are sufficient conditions to guarantee a permutation, and what is the chance that a non-permutation generates a false positive (I would hope ~1/C for each C you try, but maybe not).
it's a permutation if and only if there are no duplicate values in the array, should be easy to check that in O(N)
Depending on how much space you have, relative to N, you might try using hashing and buckets.
That is, iterate over the entire list, hash each element, and store it in a bucket. You'll need to find a way to reduce bucket collisions from the hashes, but that is a solved problem.
If an element tries to go into a bucket with an item identical to it, it is a permutation.
This type of solution would be O(N) as you touch each element only once.
However, the problem with this is whether space M is larger than N or not. If M > N, this solution will be fine, but if M < N, then you will not be able to solve the problem with 100% accuracy.
First, an information theoretic reason why this may be possible. We can trivially check that the numbers in the array are in bounds in O(N) time and O(1) space. To specify any such array of in-bounds numbers requires N log N bits of information. But to specify a permutation requires approximately (N log N) - N bits of information (Stirling's approximation). Thus, if we could acquire N bits of information during testing, we might be able to know the answer. This is trivial to do in N time (in fact, with M static space we can pretty easily acquire log M information per step, and under special circumstances we can acquire log N information).
On the other hand, we only get to store something like M log N bits of information in our static storage space, which is presumably much less than N, so it depends greatly what the shape of the decision surface is between "permutation" and "not".
I think that this is almost possible but not quite given the problem setup. I think one is "supposed" to use the cycling trick (as in the link that Iulian mentioned), but the key assumption of having a tail in hand fails here because you can index the last element of the array with a permutation.
The sum and the product will not guarantee the correct answer, since these hashes are subject to collisions, i.e. different inputs might potentially produce identical results. If you want a perfect hash, a single-number result that actually fully describes the numerical composition of the array, it might be the following.
Imagine that for any number i in [1, N] range you can produce a unique prime number P(i) (for example, P(i) is the i-th prime number). Now all you need to do is calculate the product of all P(i) for all numbers in your array. The product will fully and unambiguously describe the composition of your array, disregarding the ordering of values in it. All you need to do is to precalculate the "perfect" value (for a permutation) and compare it with the result for a given input :)
Of course, the algorithm like this does not immediately satisfy the posted requirements. But at the same time it is intuitively too generic: it allows you to detect a permutation of absolutely any numerical combination in an array. In your case you need to detect a permutation of a specific combination 1, 2, ..., N. Maybe this can somehow be used to simplify things... Probably not.
Alright, this is different, but it appears to work!
I ran this test program (C#):
static void Main(string[] args) {
for (int j = 3; j < 100; j++) {
int x = 0;
for (int i = 1; i <= j; i++) {
x ^= i;
}
Console.WriteLine("j: " + j + "\tx: " + x + "\tj%4: " + (j % 4));
}
}
Short explanation: x is the result of all the XORs for a single list, i is the element in a particular list, and j is the size of the list. Since all I'm doing is XOR, the order of the elements don't matter. But I'm looking at what correct permutations look like when this is applied.
If you look at j%4, you can do a switch on that value and get something like this:
bool IsPermutation = false;
switch (j % 4) {
case 0:
IsPermutation = (x == j);
break;
case 1:
IsPermutation = (x == 1);
break;
case 2:
IsPermutation = (x == j + 1);
break;
case 3:
IsPermutation = (x == 0);
break;
}
Now I acknowledge that this probably requires some fine tuning. It's not 100%, but it's a good easy way to get started. Maybe with some small checks running throughout the XOR loop, this could be perfected. Try starting somewhere around there.
it looks like asking to find duplicate in array with stack machine.
it sounds impossible to know the full history of the stack , while you extract each number and have limited knowledge of the numbers that were taken out.
Here's proof it can't be done:
Suppose by some artifice you have detected no duplicates in all but the last cell. Then the problem reduces to checking if that last cell contains a duplicate.
If you have no structured representation of the problem state so far, then you are reduced to performing a linear search over the entire previous input, for EACH cell. It's easy to see how this leaves you with a quadratic-time algorithm.
Now, suppose through some clever data structure that you actually know which number you expect to see last. Then certainly that knowledge takes at least enough bits to store the number you seek -- perhaps one memory cell? But there is a second-to-last number and a second-to-last sub-problem: then you must similarly represent a set of two possible numbers yet-to-be-seen. This certainly requires more storage than encoding only for one remaining number. By a progression of similar arguments, the size of the state must grow with the size of the problem, unless you're willing to accept a quadratic-time worst-case.
This is the time-space trade-off. You can have quadratic time and constant space, or linear time and linear space. You cannot have linear time and constant space.
Check out the following solution. It uses O(1) additional space.
It alters the array during the checking process, but returns it back to its initial state at the end.
The idea is:
Check if any of the elements is out of the range [1, n] => O(n).
Go over the numbers in order (all of them are now assured to be in the range [1, n]), and for each number x (e.g. 3):
go to the x'th cell (e.g. a[3]), if it's negative, then someone already visited it before you => Not permutation. Otherwise (a[3] is positive), multiply it by -1.
=> O(n).
Go over the array and negate all negative numbers.
This way, we know for sure that all elements are in the range [1, n], and that there are no duplicates => The array is a permutation.
int is_permutation_linear(int a[], int n) {
int i, is_permutation = 1;
// Step 1.
for (i = 0; i < n; ++i) {
if (a[i] < 1 || a[i] > n) {
return 0;
}
}
// Step 2.
for (i = 0; i < n; ++i) {
if (a[abs(a[i]) - 1] < 0) {
is_permutation = 0;
break;
}
a[i] *= -1;
}
// Step 3.
for (i = 0; i < n; ++i) {
if (a[i] < 0) {
a[i] *= -1;
}
}
return is_permutation;
}
Here is the complete program that tests it:
/*
* is_permutation_linear.c
*
* Created on: Dec 27, 2011
* Author: Anis
*/
#include <stdio.h>
int abs(int x) {
return x >= 0 ? x : -x;
}
int is_permutation_linear(int a[], int n) {
int i, is_permutation = 1;
for (i = 0; i < n; ++i) {
if (a[i] < 1 || a[i] > n) {
return 0;
}
}
for (i = 0; i < n; ++i) {
if (a[abs(a[i]) - 1] < 0) {
is_permutation = 0;
break;
}
a[abs(a[i]) - 1] *= -1;
}
for (i = 0; i < n; ++i) {
if (a[i] < 0) {
a[i] *= -1;
}
}
return is_permutation;
}
void print_array(int a[], int n) {
int i;
for (i = 0; i < n; i++) {
printf("%2d ", a[i]);
}
}
int main() {
int arrays[9][8] = { { 1, 2, 3, 4, 5, 6, 7, 8 },
{ 8, 6, 7, 2, 5, 4, 1, 3 },
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 1, 1, 2, 3, 4, 5, 6, 7 },
{ 8, 7, 6, 5, 4, 3, 2, 1 },
{ 3, 5, 1, 6, 8, 4, 7, 2 },
{ 8, 3, 2, 1, 4, 5, 6, 7 },
{ 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 8, 4, 2, 1, 3, 5, 6 } };
int i;
for (i = 0; i < 9; i++) {
printf("array: ");
print_array(arrays[i], 8);
printf("is %spermutation.\n",
is_permutation_linear(arrays[i], 8) ? "" : "not ");
printf("after: ");
print_array(arrays[i], 8);
printf("\n\n");
}
return 0;
}
And its output:
array: 1 2 3 4 5 6 7 8 is permutation.
after: 1 2 3 4 5 6 7 8
array: 8 6 7 2 5 4 1 3 is permutation.
after: 8 6 7 2 5 4 1 3
array: 0 1 2 3 4 5 6 7 is not permutation.
after: 0 1 2 3 4 5 6 7
array: 1 1 2 3 4 5 6 7 is not permutation.
after: 1 1 2 3 4 5 6 7
array: 8 7 6 5 4 3 2 1 is permutation.
after: 8 7 6 5 4 3 2 1
array: 3 5 1 6 8 4 7 2 is permutation.
after: 3 5 1 6 8 4 7 2
array: 8 3 2 1 4 5 6 7 is permutation.
after: 8 3 2 1 4 5 6 7
array: 1 1 1 1 1 1 1 1 is not permutation.
after: 1 1 1 1 1 1 1 1
array: 1 8 4 2 1 3 5 6 is not permutation.
after: 1 8 4 2 1 3 5 6
Java solution below answers question partly. Time complexity I believe is O(n). (This belief based on the fact that solution doesn't contains nested loops.) About memory -- not sure. Question appears first on relevant requests in google, so it probably can be useful for somebody.
public static boolean isPermutation(int[] array) {
boolean result = true;
array = removeDuplicates(array);
int startValue = 1;
for (int i = 0; i < array.length; i++) {
if (startValue + i != array[i]){
return false;
}
}
return result;
}
public static int[] removeDuplicates(int[] input){
Arrays.sort(input);
List<Integer> result = new ArrayList<Integer>();
int current = input[0];
boolean found = false;
for (int i = 0; i < input.length; i++) {
if (current == input[i] && !found) {
found = true;
} else if (current != input[i]) {
result.add(current);
current = input[i];
found = false;
}
}
result.add(current);
int[] array = new int[result.size()];
for (int i = 0; i < array.length ; i ++){
array[i] = result.get(i);
}
return array;
}
public static void main (String ... args){
int[] input = new int[] { 4,2,3,4,1};
System.out.println(isPermutation(input));
//output true
input = new int[] { 4,2,4,1};
System.out.println(isPermutation(input));
//output false
}
int solution(int A[], int N) {
int i,j,count=0, d=0, temp=0,max;
for(i=0;i<N-1;i++) {
for(j=0;j<N-i-1;j++) {
if(A[j]>A[j+1]) {
temp = A[j+1];
A[j+1] = A[j];
A[j] = temp;
}
}
}
max = A[N-1];
for(i=N-1;i>=0;i--) {
if(A[i]==max) {
count++;
}
else {
d++;
}
max = max-1;
}
if(d!=0) {
return 0;
}
else {
return 1;
}
}