Related
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
I have undergone one problem in C in logic creation.What i have to do is:
1)I have array a[215] = {0,1,2,3,4,5}.Now i have to add two minimum elements of this array and then position the newly element obtained in the same array such that it will maintain the increasing order of the array(a[],which was already sorted array).
(2)I also have to take care that the two minimum added elements must not participate in sorting and addition again, they must be fixed at their position once if they are already added, but the newly obtained element by addition can participate in addition and sorting again.
eg:
we add two minimum element 0 and 1, 0+1=1, so "1" is the result obtained by addition, now this "1" must be positioned in a[] such that still there should be increasing order.
so :
0 1 1(added here) 2 3 4 5
Now we have to again find the minimum two nodes (please read the comment (2) again to understand well) .We cannot add 0 abnd 1 again because they have already participated in in the addition. so this time we will add 1 and 2(this one is at index three, please don't get confused wwith the one at index two). so we get 1+2=3
0 1 1 2 3 3 4 5 we again positioned 3 to maintain increasing order.
we repeat again: for element at index 4 and 5(because we have already done addition for element at index 0,1 and 2,3) we will get 3+3=6, again position it in a[].
0 1 1 2 3 3 4 5 6 this time 6 is greater then 4 and 5 so it will appear after 5 to maintain increasing order.
At last we will get a[] like this:
a[ ]= [0 1 1 2 3 3 4 5 6 9 15].
so the addition held was between index 0,1 and 2,3 and 4,5 and 6, 7 and 8,9 and at last we have 15 which is last one, so here we stops.
Now coming to how much i have already implemented :
I have implemented this addition part, which do addition on array a[ ] = [0 1 2 3 4 5].
And puts the newly obtained element at last index(which is dataSize in my code, please see data[dataSize++]=newItem).
Each time i call the function PositionAdjustOfNewItem(data,dataSize); giving the array(which also contains the newly obtained element at last index)as first argument and the newly obtained size as second argument.Here is the code below:
for(i=0;i<14;i++)
for(j=1;j<15;j++)
{
// This freq contains the given array (say a[]=[0 1 2 3 4 5] in our case and
// it is inside the struct Array { int freq}; Array data[256]; )
newItem.freq = data[i].freq + data[j].freq;
data[dataSize++]=newItem;
PositionAdjustOfNewItem(data,dataSize); // Logic of this function I am not able to develop yet. Please help me here
i=i+2;
j=j+1;
}
I am not able to implement the logic of function PositionAdjustOfNewItem(), which pass the array data[], which contains all the elements and the newly added element at last index and in second argument i pass the newly obtained size of array after putting the newly obtained element at last index.
Each time when i add two elements i call this PositionAdjustOfNewItem() passing the newly added elements at last and newly obtained size. which is supposed to be sorted by this function PositionAdjustOfNewItem().
This PositionAdjustOfNewItem() have as least complexity as possible.The part above the code was just to make you aware of mechanish i am using to add elements, You have nothing to do there, I need your help only in getting the logic of PositionAdjustOfNewItem().
(Even i already done it with qsort() but complexity is very high). so need any other way?
How about something like this:
NOTE: In your example, you are dealing with an array of some structure which has freq as a field. In my example, I am using simple integer arrays.
#include <stdio.h>
#include <string.h>
int a[] = {0,1,2,3,4,5};
int main(void) {
int i,j;
// Initialize a new array big enough to hold the result.
int* array = new int[15];
memcpy(array, a, 6*sizeof(int));
int length=6;
// Loop over consecutive indeces.
for (i=0; i+1<length; i+=2) {
// Get the sum of these two indeces.
int sum=array[i]+array[i+1];
// Insert the sum in the array, shifting elements where necessary.
for (j=length-1; j>i+1; j--) {
if (sum >= array[j]) {
// Insert here
break;
} else {
// Shift
array[j+1]=array[j];
}
}
array[j+1]=sum;
// We now have one more element in the array
length++;
}
// Display the array.
printf("{ ");
for (j=0; j<length; j++) {
printf("%d ", array[j]);
}
printf("}\n");
}
To insert the sum, what is done is we traverse the array from the end to the front, looking for the spot it belongs. If we encounter a value less then the sum, then we simply insert it after this value. Otherwise (i.e. value is greater than the sum), we need to insert it before. Thus, the value needs to be shifted one position higher, and then we check the previous value. Continue until we find the location.
If you only need the PositionAdjustNewItem method, then this is what it would look like:
void PositionAdjustOfNewItem(int* array, int length) {
int newItem = array[length-1];
for (int j=length-2; j>i+1; j--) {
if (sum >= array[j]) {
// Insert here
break;
} else {
// Shift
array[j+1]=array[j];
}
}
array[j+1]=sum;
}
When you run it, it produces the output you expect.
$ ./a.out
{ 0 1 1 2 3 3 4 5 6 9 15 }
void doSomething()
{
int hist[5] = { 0 };
int num_bins = 5;
int indices[10] = { 0, 0, 2, 3, 3, 3, 3, 4, 4, 4 };
int num_indices = 10;
int i;
for (i = 0; i < num_indices; i++)
{
hist[indices[i]]++;
}
for (i = 0; i < num_bins; i++)
{
printf("%d ", hist[i]);
}
printf("\n");
}
Assume I have correct libraries this is a conceptual question from class. I am wondering how the answer comes out to 2 0 1 4 3 for the array.
The line
hist[indices[i]]++
Says "go to the element of the hist array at index indices[i], then increment it." If you think of the array as a list of counters, this says to increment the counter at position indices[i].
This code builds a histogram of the frequencies of various numbers in an array. The idea behind the above code is to iterate over the array and increment the frequencies of each element.
Hope this helps!
The elements in indices range from 0 to 4, which are all valid index of the 5 elements array hist. (That's why the array is named indices, as it's for indexing)
So for instance, i is 2, then indices[i] is 2.
hist[indices[i]]++;
is equivalent to
hist[2]++;
For small questions like this you should try to write down the state of every element of each array on a piece of paper and execute your code step by step. You could also write the code to print useful information in runtime.
If after that you still can't figure it out then it's worth asking here. Otherwise you won't be learning much.
This program increments the 0's in
hist
as it indexes appear in
indices[10]
eg.
when you have the first for interation
hist[indices[0]]++ // hist[0]++ --> 0++;
It looks like "2 0 1 4 3" is a count of how many items exists in the array. 2 0's, 0 1's, 1 2, 4 3's and 3 4's. So the query is counting how many instances of each number are in the array and then printing out that result.
So the statement:
hist[indices[i]]++
find the value of indices[], then increments the int in the hist[] array by 1 giving you a count of how many of those elements are in the array.
1.As you have partially initialized your array, compiler sets other values to 0
2.hist[indices[i]]++; this statement increments the value of hist[i], for the current value of i
3.the value of i is denoted by your array indices[]
4.try having values grater than 5 in your array named indices[].
First let me say that this is hw so I am looking for more advice than an answer. I am to write a program to read an input sequence and then produce an array of links giving the values in ascending order.
The first line of the input file is the length of the sequence (n) and each of the remaining n lines is a non-negative integer. The
first line of the output indicates the subscript of the smallest input value. Each of the remaining output lines is a triple
consisting of a subscript along with the corresponding input sequence and link values.
(The link values are not initialized before the recursive sort begins. Each link will be initialized to -1 when its sequence value is placed in a single element list at bottom of recursion tree)
The output looks something like this:
0 3 5
1 5 2
2 6 3
3 7 -1
4 0 6
5 4 1
6 1 7
7 2 0
Where (I think) the last column is the subscripts, the center is the unsorted array, and the last column is the link values. I have the code already for the mergeSort and understand how it works I am only just confused and how the links get put into place.
I used vector of structures to hold the three values of each line.
The major steps are:
initialize the indexes and read the values from the input
sort the vector by value
determine the links
sort (back) the vector by index
Here is a sketch of the code:
struct Element {
int index;
int value;
int nextIndex; // link
}
Element V[N + 1];
int StartIndex;
V[i].index = i;
V[i].value = read_from_input;
sort(V); // by value
startIndex = V[0].index;
V[i].nextIndex = V[i + 1].index;
V[N].nextIndex = -1;
sort(V); // by index
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.