Related
I have to find maximum sum of elements in integer array, according to the rule:
If second (or any consecutive) element is added to the sum - only half of the value is added. To avoid this, you can skip one elememnt.
For example we have an input like this [4, 2, 5, 1, 5]
The result should be 14. In this case, we took elements at 0, 2 and 4 positions (4 + 5 + 5 = 14), and skipped elements at positions 1 and 3
The other example would be input like [3, 1, 10, 6, 3, 10]
In this case the answer should be 26. We took elements at positions 0, 2, 3, 5 and skipped elements at positions 1 and 4. Therefore sum counts as:
3 + 0 + 10 + 6/2 + 0 + 10 = 26
Could anyone please explain me the algorithm to solve this problem? Or at least the direction in which i shoudl try to solve it. Does this task has anything to do with dynamic programming? Or maybe with recursion?
Thanks in advance
A simple optimum solution is to iteratively calculate two sums, both corresponding to a maximum up to the current index i,
the first sum (sum0) assuming current value arr[i] is not used, the second sum (sum1) assuming the current value arr[i] is used.
sum0_new = max (sum0, sum1);
sum1_new = max (sum0 + x, sum1 + x/2);
Complexity: O(N)
Code:
This is a simple C++ code to illustrate the algorithm.
This implementation assumes integer division par 2. Easy to modify if it is not the case.
Output: 14 26
#include <iostream>
#include <vector>
#include <algorithm>
int max_sum (const std::vector<int>& arr) {
int sum0 = 0;
int sum1 = 0;
for (int x: arr) {
int temp = sum0;
sum0 = std::max (sum0, sum1);
sum1 = std::max (temp + x, sum1 + x/2);
}
return std::max (sum0, sum1);
}
int main() {
std::vector<std::vector<int>> examples = {
{4, 2, 5, 1, 5},
{3, 1, 10, 6, 3, 10}
};
for (std::vector<int>& arr: examples) {
int sum = max_sum (arr);
std::cout << sum << '\n';
}
return 0;
}
Is it possible to assign some values to an array instead of all? To clarify what I want:
If I need an array like {1,0,0,0,2,0,0,0,3,0,0,0} I can create it like:
int array[] = {1,0,0,0,2,0,0,0,3,0,0,0};
Most values of this array are '0'. Is it possible to skip this values and only assign the values 1, 2 and 3? I think of something like:
int array[12] = {0: 1, 4: 2, 8: 3};
Is it possible to skip this values and only assign the values 1, 2 and 3?
In C, Yes. Use designated initializer (added in C99 and not supported in C++).
int array[12] = {[0] = 1, [4] = 2, [8] = 3};
Above initializer will initialize element 0, 4 and 8 of array array with values 1, 2 and 3 respectively. Rest elements will be initialized with 0. This will be equivalent to
int array[12] = {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0};
The best part is that the order in which elements are listed doesn't matter. One can also write like
int array[12] = {[8] = 3, [0] = 1, [4] = 2};
But note that the expression inside [ ] shall be an integer constant expression.
Here is my trivial approach:
int array[12] = {0};
array[0] = 1; array[4] = 2; array[8] = 3;
However, technically speaking, this is not "initializing" the array :)
An alternative way to do it would be to give default value by memset for all elements in the array, and then assign the specific elements:
int array[12];
memset(array, 0, sizeof(int) * 12); //if the default value is 0, this may not be needed
array[0] = 1; array[4] = 2; array[8] = 3;
Standard C17
The standard (C17, N2176) has an interesting example in § 6.7.9(37):
EXAMPLE 13 Space can be “allocated” from both ends of an array by using a single designator:
int a[MAX] = {
1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0
};
In the above, if MAX is greater than ten, there will be some
zero-valued elements in the middle; if it is less than ten, some of
the values provided by the first five initializers will be overridden
by the second five.
Example
#include <stdio.h>
#define MAX 12
int main(void)
{
// n2176, § 6.7.9(37)
int a[MAX] = {
1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0
};
for (size_t i = 0; i < MAX; i++) {
printf("%d\n", a[i]);
}
return 0;
}
Output:
1
3
5
7
9
0 <-- middle element, defaults to zero
0 <-- middle element, defaults to zero
8
6
4
2
0
I was asked:
Replace each number in a list by sum of remaining elements, the list is not sorted.
So suppose if we have a list of numbers like {2, 7, 1, 3, 8}, now we are to replace each element with sum of rest of elements. The output should be:
{(7 + 1 + 3 + 8), (2 + 1 + 3 + 8), (2 + 7 + 3 + 8), (2 + 7 + 1 + 8), (2 + 7 + 1 + 3)}
== {19, 14, 20, 18, 13}
I answered an obvious solution:
First evaluate sum of all numbers then subtract each element from sum.
So for above list sum is 2 + 7 + 1 + 3 + 8 = 21, then for output do like:
{sum - 2, sum - 7, sum - 1, sum - 3, sum - 8}
{21 - 2, 21 - 7, 21 - 1, 21 - 3, 21 - 8}
== {19, 14, 20, 18, 13}
It needs only two iterations of list.
Then Interviewer asked me: Now do it without subtraction? and I couldn't answer :(
Is other solution possible? Can some share any other trick? A better trick is possible?
Lets extra memory space can be used (I asked after a few minutes of try, even then I couldn't answer).
One possibility would be to compute prefix and suffix sums of your array and then combine the appropriate entries. This would still be O(n) but needs more memory space so I think your original method is better.
In other words, from {2, 7, 1, 3, 8} compute {2, 2+7, 2+7+1, 2+7+1+3, 2+7+1+3+8} and {2+7+1+3+8, 7+1+3+8, 1+3+8, 3+8, 8} and then add the appropriate entries.
The solution is to sum everything but the element. Then you don't have to subtract after the fact. You just skip adding the element at the current index.
Alternatively, you could get a subset of the list that excludes the element at the current index, then just sum the subset together. Pretty much the same thing as my first suggestion with more implementation detail.
C++ implementation. O(n) and done by keeping sums of all elements before and after a certain index.
#include <iostream>
int main() {
int a[] = {2,7,1,3,8};
int prefix[5]; // Sum of all values before current index
int suffix[5]; // Sum of all values after current index
prefix[0] = 0;
suffix[4] = 0;
for(int i = 1; i < 5; i++) {
prefix[i] = prefix[i-1] + a[i-1];
suffix[4 - i] = suffix[4 - i + 1] + a[4 - i + 1];
}
// Print result
for (int i = 0; i < 5; i++) {
std::cout << prefix[i] + suffix[i] << " ";
}
std::cout << std::endl;
}
I can't think anything better than yours.
But how about this :
Create a (n-1)xn matrix:
[ 2, 7, 1, 3, 8 ]
| 7, 1, 3, 8, 2 | rotate by 1
| 1, 3, 8, 2, 7 | by 2
| 3, 8, 2, 7, 1 | by 3
| 8, 2, 7, 1, 3 | by 4
Then Sum up the columns
C++'s std::rotate_copy can be used to create matrix
std::vector<int> v1 {2, 7, 1, 3, 8 };
std::vector<int> v2 (v1.size());
int i,j;
std::vector< std::vector<int> > mat;
for (int i=1; i<v1.size();++i){
std::rotate_copy(v1.begin(),v1.begin()+i,v1.end(),v2.begin());
mat.push_back(v2);
}
for(j=0;j<v1.size();++j)
for(i=0;i<v1.size()-2;++i)
v2[j]+=mat[i][j];
for(i=0;i<v2.size();++i)
std::cout<<v2[i]<<" ";
#include <iostream.h>
#include <stdio.h>
int main() {
int a[] = {2,7,1,3,8};
int sum[5]={0};
for(int j = 0; j < 5; j++){
for(int i = 1; i < 5; i++) {
sum[j]=sum[j]+a[(j+i+5)%5];
}
printf("%d ", sum[j]); }
}
Instead of subtracting the element you can add the element multiplied by -1. Multiplication and addition are allowed operations, I guess.
I have a C array fftArray[64] that contains values that I want averaged and placed into another array frequencyBar[8]. Getting the average of the entire array would be easy enough using a for statement.
int average, sum = 0;
for (i = 0; i < 64; i++)
{
sum += fftArray[i];
}
average = sum/64;
But I just can't seem to figure out how to get the average from fftArray[0] through fftArray[8] and store this in frequencyBar[0], the average of fftArray[9] through fftArray[16] and store this in frequencyBar[1], etc. Can anyone help me out with this? Thanks
This looks like a homework assignment, so, rather than give you the outright answer, I'd rather just point you in the right direction...
use a nested loop (one inside the other). One loop cycles 0-7, the other one 0 - 63. Use the smaller one to populate your sliced averages.
or better yet use the % operator to see when you've gone through 8 elements and do an average of your total, then reset the total for the next set. Then you'll have learned how to use the % operator too! :)
[EDIT]
ok, if not homework then something like this... I haven't written C in 5 years, so treat this as pseudo code:
//assuming you have a fftArray[64] with data, as per your question
int i,sum,avCounter,total;
int averages[8];
for(i=0 , avCounter=0, total=0 ; i<64; ){
total += fftArray[i];
if(++i % 8 == 0){ //%gives you the remainder which will be 0 every 8th cycle
averages[avCounter++] = total / 8
total = 0; //reset for next cycle
}
}
I think this will work better than a nested loop... but I'm not sure since % is division which is more processor heavy than addition... however... I doubt anyone would notice :)
int i, j;
for (i = 0; i < 8; i++) {
int sum = 0;
for (j = 0; j < 8; j++) {
sum += fftArray[ 8*i + j ];
}
frequencyBar[i] = sum / 8;
}
Bonus exercise: Optimize this code for speed on your chosen platform.
TF,
DISCLAIMER: This code is just off the top of my head... it hasn't even been compiled, let alone tested.
// returns the average of array[first..last] inclusive.
int average(int[] array, int first, int last) {
int sum = 0;
for (i = first; i <= last; i++)
sum += array[i];
return sum / (last - first + 1); // not sure about the +1
}
Then what you'd do is loop through the indexes of your frequencyBar array [0..7], setting frequencyBar[i] = average(array, first, last);... the tricky bit is calculating the first and last indexes... try i*8 and (i+1)*8 respectively... that may not be exactly right, but it'll be close ;-)
Cheers. Keith.
EDIT: Bored... waiting for my test results to come back. No news is good news, right? ;-)
It turns out that passing the length is a fair bit simpler than passing the last index.
#include <stdio.h>
int sum(int array[], int first, int length) {
int sum = 0;
for (int i = first; i < first+length; i++)
sum += array[i];
return sum;
}
double average(int array[], int first, int length) {
double total = sum(array, first, length);
#ifdef DEBUG
printf("DEBUG: [%2d..%2d] %d", first, first+length-1, array[first]);
for (int i = first+1; i < first+length; i++)
printf(" + %d", array[i]);
printf(" = %d / %d = %f\n", (int)total, length, total/length);
#endif
return total / length;
}
int main(int argc, char* argv[]) {
int array[] = { // average
1, 2, 3, 4, 5, 1, 2, 3, // 2.625
4, 5, 1, 2, 3, 4, 5, 1, // 3.125
2, 3, 4, 5, 1, 2, 3, 4, // 3
5, 1, 2, 3, 4, 5, 1, 2, // 2.875
3, 4, 5, 1, 2, 3, 4, 5, // 3.375
1, 2, 3, 4, 5, 1, 2, 3, // 2.625
4, 5, 1, 2, 3, 4, 5, 1, // 3.125
2, 3, 4, 5, 1, 2, 3, 4 // 3
};
double frequency[8];
for (int i = 0; i < 8; i++)
frequency[i] = average(array, i*8, 8);
for (int i = 0; i < 8; i++)
printf("%f ", frequency[i]);
printf("\n");
}
Watch your sum doesn't wrap around if fftArray has large value in!
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Reordering of array elements
In given array of elements like [a1,a2,a3,..an,b1,b2,b3,..bn,c1,c2,c3,...cn] Write a program to merge them like [a1,b1,c1,a2,b2,c2,...an,bn,cn].
We have to do it in O(1) extra space.
Sample Testcases:
Input #00:
{1,2,3,4,5,6,7,8,9,10,11,12}
Output #00:
{1,5,9,2,6,10,3,7,11,4,8,12}
Explanation:
Here as you can notice, the array is of the form
{a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4}
EDIT:
I got it in Amazon placement test. Have been trying it for a long time.
PLease provide psuedo code. What i tried is finding new position p for second element e(1st is already at correct position), inserting e at p and repeating the same for the old element at position p. But this is ending in a cycle.
I tried detecting cycle and incrementing the starting position by 1. But even this is not working.
EDIT2:
#include <iostream>
using namespace std;
int pos(int i, int n)
{
if(i<n)
{
return 3*i;
}
else if(i>=n && i<2*n)
{
return 3*(i-n) + 1;
}
else if(i>=2*n && i<3*n)
{
return 3*(i-2*n) + 2;
}
return -1;
}
void printn(int* A, int n)
{
for(int i=0;i<3*n;i++)
cout << A[i]<<";";
cout << endl;
}
void merge(int A[], int n)
{
int j=1;
int k =-1;
int oldAj = A[1];
int count = 0;
int temp;
while(count<3*n-1){
printn(A,n);
k = pos(j,n);
temp = A[k];
A[k] = oldAj;
oldAj = temp;
j = k;
count++;
if(j==1) {j++;}
}
}
int main()
{
int A[21] = {1,4,7,10,13,16,19,2,5,8,11,14,17,20,3,6,9,12,15,18,21};
merge(A,7);
cin.get();}
This is the so called in-place in-shuffle algorithm, and it's an extremely hard task if you want to do it efficiently. I'm just posting this entry so people don't post their so called "solutions" claiming that it can be extended to work with O(1) space, without any proof...
Here is a paper for a simpler case when the list is in the form: a1 a2 a3 ... an b1 b2 b3 .. bn:
http://arxiv.org/PS_cache/arxiv/pdf/0805/0805.1598v1.pdf
Here's is a description of an algorithm with 3 elements of extra space and O(n^2) complexity:
sa, sb, sc are, respectively, next source index for a, b and c sequences.
d is the copy destination index.
On each iterarion:
Copy elements at sa, sb and sc to temporary storage
Shift the array elements to the left to fill in the now vacant indices sa, sb and sc
This leaves three empty positions at d
Copy the three elements from temporary storage to empty positions.
Example (dots indicate "empty" positions):
First iteration:
copy to tmp: ., 2, 3, 4, ., 6, 7, 8, .,10,11,12
1 5 9
shift: ., ., ., 2, 3, 4, 6, 7, 8,10,11,12
copy to dst: 1, 5, 9, 2, 3, 4, 6, 7, 8,10,11,12
Second iteration:
copy to tmp: 1, 5, 9, ., 3, 4, ., 7, 8, .,11,12
2 6 10
shift: 1, 5, 9, ., ., ., 3, 4, 7, 8,11,12
copy to dst: 1, 5, 9, 2, 6,10, 3, 4, 7, 8,11,12
Third iteration:
copy to tmp: 1, 5, 9, 2, 6,10, ., 4, ., 8, .,12
3 7 11
shift: 1, 5, 9, 2, 6,10, ., ., ., 4, 8,12
copy to dst: 1, 5, 9, 2, 6,10, 3, 7 11, 4, 8,12
EDIT:
And here's a working program (it takes a bit more than a verbal description :)))
#include <stdio.h>
#define N 4
int a[] = {1, 2,3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
void
rearrange ()
{
int i;
int d;
int sa, sb, sc;
int tmp [3];
d = 0;
sa = 0;
sb = sa + N;
sc = sb + N;
while (sc < N*3)
{
/* Copy out. */
tmp [0] = a [sa];
tmp [1] = a [sb];
tmp [2] = a [sc];
/* Shift */
for (i = sc; i > sb + 1; --i)
a [i] = a [i - 1];
for (i = sb + 1; i > sa + 2; --i)
a [i] = a [i - 2];
sa += 3;
sb += 2;
sc++;
/* Copy in. */
a [d++] = tmp [0];
a [d++] = tmp [1];
a [d++] = tmp [2];
}
}
int
main ()
{
int i;
rearrange ();
for (i = 0; i < N*3; ++i)
printf ("%d\n", a [i]);
putchar ('\n');
return 0;
}
Appears to work. shrug
This is the general solution to the problems like yours.
First of all, for each source index you know the destination index. Now, you go like that:
Take the first item. Find its final place. Memorize the item at that place, and store the first item there. Now, find the place where the memorized item belongs to, and put that item there, memorizing that replaced item. Continue the process until it hits the place of the first item (obviously).
If you've replaced all the items, you are finished. If not, take the first non-transferred item and continue repeat the procedure from step 1, starting with that item.
You'll need to mark which items you've transferred already. There are different ways to do it: for example, you can use one bit from the item's storage.
Okay, the solution above is not exactly O(1), as it requires N extra bits. Here is the outline of O(1) solution by place, though less efficient:
Consider the items a1, b1, c1. They need to be located at the first 3 places of the result. So we are doing the following: remembering a1, b1, c1, compacting the array except these three items to the back (so it looks like this: , , , a2, a3, ..., an, b2, b3, ..., bn, c2, c3, ..., cn), and put the items a1, b1, c1 at their places at the beginning. Now, we found the place for the first 3 items, so continue this procedure for a2, b2, c2 and so on.
Edit:
let's consider the time complexity of the outline above. Denote list size 3*n. We need n steps. Each single compactification of the list can be done in one pass, and therefore is O(n). All the other operations inside a step are O(1), so we get altogether n * O(n) = O(n^2) complexity. This is far from the best solution, however, as #yi_H mentions, linear-time solution requires heavy usage of more-or-less advanced mathematics.
I can't find any O(n) algorithm but this is O(n^2) in-place one, I'll move triples to the last each time code is tested by given input, is in C#, may be is buggy, If is so let me know:
int[] a = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
int m = a.Length / 3;
int firstB = a[m];
for (int i = m-1; i > 0; i--)
{
int second = a[3 * m - 3];
int third = a[3 * m - 2];
//a[i + 2 * m] = a[i +2 * m];
a[3 * m - 2] = a[2 * m - 1];
a[3 * m - 3] = a[m - 1];
for (int j = m - 1; j < 2 * m - 1; j++)
{
a[j] = a[j + 1];
}
for (int j = 2 * m - 2; j < 3 * m - 3; j++)
{
a[j] = a[j + 2];
}
a[3 * m - 5] = second;
a[3 * m - 4] = third;
m--;
}
a[1] = firstB;
Here we have x * y numbers:
a_11, a_12, ..., a_1x,
a_21, a_22, ..., a_2x,
...
a_y1, a_y2, ..., a_yx
then the number a_ij has the index i*x + j in an array;
after your program, the new index will be
j * y + i
in your interview
{a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4}
x is 4, and y is 3,
so with the index ``n''
i = (n - (n % 4)) / 4;
j = n % 4;
now you can calculate the new index with i, j, x, y.
Good Luck.