How to delete an element from an array in C? - arrays

I've tried shifting elements backwards but it is not making the array completely empty.
for(i=pos;i<N-count;i++)
{
A[i]=A[i+1];
}
Actually, I've to test for a key value in an input array and if the key value is present in the array then I've to remove it from the array. The loop should be terminated when the array becomes empty. Here "count" represents the number of times before a key value was found and was removed. And, "pos" represents the position of the element to be removed. I think dynamic memory allocation may help but I've not learned it yet.

From your description and code, by "delete" you probably mean shift the values to remove the given element and shorten the list by reducing the total count.
In your example, pos and count would be/should be the similar (off by 1?) .
The limit for your for loop isn't N - count. It is N - 1
So, you want:
for (i = pos; i < (N - 1); i++) {
A[i] = A[i + 1];
}
N -= 1;
To do a general delete, given some criteria (a function/macro that matches on element(s) to delete, such as match_for_delete below), you can do the match and delete in a single pass on the array:
int isrc = 0;
int idst = 0;
for (; isrc < N; ++isrc) {
if (match_for_delete(A,isrc,...))
continue;
if (isrc > idst)
A[idst] = A[isrc];
++idst;
}
N = idst;

Related

Rebuild an array of integers after summing the digits of each element

We have an strictly increasing array of length n ( 1 < n < 500) . We sum the digits of each element to create a new array with each elements values is in range 1 to 500.The task is to rebuild the old array from the new one. since there might be more than one answer, we want the answers with the minimum value of the last element.
Example:
3 11 23 37 45 123 =>3 2 5 10 9 6
now from the second array, we can rebuild the original array in many different ways for instance:
12 20 23 37 54 60
from all the possible combinations, we need the one we minimum last element.
My Thoughts so far:
The brute force way is to find all possible permutations to create each number and then create all combinations possible of all numbers of the second array and find the combination with minimum last element. It is obvious that this is not a good choice.
Using this algorithm(with exponential time!) we can create all possible permutations of digits that sum to a number in the second arrays. Note that we know the original elements were less than 500 so we can limit the death of search of the algorithm.
One way I thought of that might find the answer faster is to:
start from the last element in the new arrays and find all possible
numbers that their digit sum resulted this element.
Then try to use the smallest amount in the last step for this element.
Now try to do the same with the second to last element. If the
minimum permutation value found for the second to last element is bigger
than the one found for the last element, backtrack to the last
element and try a larger permutation.
Do this until you get to the first element.
I think this is a greed solution but I'm not very sure about the time complexity. Also I want to know is there a better solution for this problem? like using dp?
For simplicity, let's have our sequence 1-based and the input sequence is called x.
We will also use an utility function, which returns the sum of the digits of a given number:
int sum(int x) {
int result = 0;
while (x > 0) {
result += x % 10;
x /= 10;
}
return result;
}
Let's assume that we are at index idx and try to set there some number called value (given that the sum of digits of value is x[idx]). If we do so, then what could we say about the previous number in the sequence? It should be strictly less than value.
So we already have a state for a potential dp approach - [idx, value], where idx is the index where we are currently at and value denotes the value we are trying to set on this index.
If the dp table holds boolean values, we will know we have found an answer if we have found a suitable number for the first number in the sequence. Therefore, if there is a path starting from the last row in the dp table and ends at row 0 then we'll know we have found an answer and we could then simply restore it.
Our recurrence function will be something like this:
f(idx, value) = OR {dp[idx - 1][value'], where sumOfDigits(value) = x[idx] and value' < value}
f(0, *) = true
Also, in order to restore the answer, we need to track the path. Once we set any dp[idx][value] cell to be true, then we can safe the value' to which we would like to jump in the previous table row.
Now let's code that one. I hope the code is self-explanatory:
boolean[][] dp = new boolean[n + 1][501];
int[][] prev = new int[n + 1][501];
for (int i = 0; i <= 500; i++) {
dp[0][i] = true;
}
for (int idx = 1; idx <= n; idx++) {
for (int value = 1; value <= 500; value++) {
if (sum(value) == x[idx]) {
for (int smaller = 0; smaller < value; smaller++) {
dp[idx][value] |= dp[idx - 1][smaller];
if (dp[idx][value]) {
prev[idx][value] = smaller;
break;
}
}
}
}
}
The prev table only keeps information about which is the smallest value', which we can use as previous to our idx in the resulting sequence.
Now, in order to restore the sequence, we can start from the last element. We would like it to be minimal, so we can find the first one that has dp[n][value] = true. Once we have such element, we then use the prev table to track down the values up to the first one:
int[] result = new int[n];
int idx = n - 1;
for (int i = 0; i <= 500; i++) {
if (dp[n][i]) {
int row = n, col = i;
while (row > 0) {
result[idx--] = col;
col = prev[row][col];
row--;
}
break;
}
}
for (int i = 0; i < n; i++) {
out.print(result[i]);
out.print(' ');
}
If we apply this on an input sequence:
3 2 5 10 9 6
we get
3 11 14 19 27 33
The time complexity is O(n * m * m), where n is the number of elements we have and m is the maximum possible value that an element could hold.
The space complexity is O(n * m) as this is dominated by the size of the dp and prev tables.
We can use a greedy algorithm: proceed through the array in order, setting each element to the least value that is greater than the previous element and has digits with the appropriate sum. (We can just iterate over the possible values and check the sums of their digits.) There's no need to consider any greater value than that, because increasing a given element will never make it possible to decrease a later element. So we don't need dynamic programming here.
We can calculate the sum of the digits of an integer m in O(log m) time, so the whole solution takes O(b log b) time, where b is the upper bound (500 in your example).

Mutating an array without extra space

I was given the following question in an interview, and couldn't find the solution.
Given is an array of chars length n, and "important section" (all chars in this section must be saved) length m where n >= m >= 0 as follows:
Without extra space, perform the following process:
Remove all occurrences of A and duplicate all occurrences of B, return a sub array of the mutated array. For example, for the above array [C,A,X,B,B,F,Q] n=7, m=5 ,output will be [C,X,B,B,B,B]. Note that the mutated array length is 6, since Q was in the redundant section and B was duplicated.
Return -1 if the operation can't be performed.
Examples:
n=2, m=2 , [A,B] => [B,B]
n=2, m=2 , [B,B] => -1 (since the result [B,B,B,B] is larger then the array)
n=3, m=2 , [A,B,C] => [B,B]
n=3, m=3 , [A,B,C] => [B,B,C]
n=3, m=2 , [Z,B,A] => [Z,B,B] (since A was in the redundant section)
Looking for a code example, Could this be done in O(n) time complexity?
Scan array to determine if is it possible to store mutated array in available space -- count As and B, and check N-M >= numB-numA
Walk array left to right: Shift elements to the left by the number of As so far (filling places of A)
Walk array right to left: Shift elements to the right by numB-B_so_far, inserting additional Bs
Start from the end of the input array. We will figure out from the back to the front what to fill in.
Look at the last significant character in the input (position m). If it is a, ignore it. Otherwise, add the symbol. Repeat until you read all the input.
This removes as. Now we will duplicate bs.
Start from the beginning of the array. Find the last value you wrote during the above steps. If it is a b, write two bs. If it is something else, just write one of them. Repeat. NOTE: if you ever "catch up", needing to write where you need to read, you don't have enough room and you output -1. Otherwise, return the part of the array from position 1 to the last read position.
Example:
Phase 1: removing A
CAXBBFQ
CAXBBFB
CAXBBBB
CAXBXBB
CAXCXBB
Phase 2: duplicating B
CAXCXBB
CXXCXBB
CXBBXBB
CXBBBBB
^^^^^^
Phase 1 is linear (we read m symbols and write no more than m).
Phase 2 is linear (we read fewer than m symbols and write no more than 2m).
m is less than n so everything is O(m) and O(n).
The code, with some optimizations, would look something like this, O(n):
// returns length of the relevant part of the mutated array or -1
public static int mutate(char[] a, int m) {
// delete As and count Bs in the relevant part
int bCount = 0, position = 0;
for (int i = 0; i < m; i++) {
if (a[i] != 'A') {
if (a[i] == 'B')
bCount++;
a[position++] = a[i];
}
}
// check if it is possible
int n = bCount + position;
if (n > a.length)
return -1;
// duplicate the Bs in the relevant part
for (int i = position - 1, index = n - 1; i >= 0; i--) {
if (a[i] != 'B') {
a[index--] = a[i];
} else {
a[index--] = 'B';
a[index--] = 'B';
}
}
return n;
}

Applying a function on sorted array

Taken from the google interview question here
Suppose that you have a sorted array of integers (positive or negative). You want to apply a function of the form f(x) = a * x^2 + b * x + c to each element x of the array such that the resulting array is still sorted. Implement this in Java or C++. The input are the initial sorted array and the function parameters (a, b and c).
Do you think we can do it in-place with less than O(n log(n)) time where n is the array size (e.g. apply a function to each element of an array, after that sort the array)?
I think this can be done in linear time. Because the function is quadratic it will form a parabola, ie the values decrease (assuming a positive value for 'a') down to some minimum point and then after that will increase. So the algorithm should iterate over the sorted values until we reach/pass the minimum point of the function (which can be determined by a simple differentiation) and then for each value after the minimum it should just walk backward through the earlier values looking for the correct place to insert that value. Using a linked list would allow items to be moved around in-place.
The quadratic transform can cause part of the values to "fold" over the others. You will have to reverse their order, which can easily be done in-place, but then you will need to merge the two sequences.
In-place merge in linear time is possible, but this is a difficult process, normally out of the scope of an interview question (unless for a Teacher's position in Algorithmics).
Have a look at this solution: http://www.akira.ruc.dk/~keld/teaching/algoritmedesign_f04/Artikler/04/Huang88.pdf
I guess that the main idea is to reserve a part of the array where you allow swaps that scramble the data it contains. You use it to perform partial merges on the rest of the array and in the end you sort back the data. (The merging buffer must be small enough that it doesn't take more than O(N) to sort it.)
If a is > 0, then a minimum occurs at x = -b/(2a), and values will be copied to the output array in forward order from [0] to [n-1]. If a < 0, then a maximum occurs at x = -b/(2a) and values will be copied to the output array in reverse order from [n-1] to [0]. (If a == 0, then if b > 0, do a forward copy, if b < 0, do a reverse copy, If a == b == 0, nothing needs to be done). I think the sorted array can be binary searched for the closest value to -b/(2a) in O(log2(n)) (otherwise it's O(n)). Then this value is copied to the output array and the values before (decrementing index or pointer) and after (incrementing index or pointer) are merged into the output array, taking O(n) time.
static void sortArray(int arr[], int n, int A, int B, int C)
{
// Apply equation on all elements
for (int i = 0; i < n; i++)
arr[i] = A*arr[i]*arr[i] + B*arr[i] + C;
// Find maximum element in resultant array
int index=-1;
int maximum = -999999;
for (int i = 0; i< n; i++)
{
if (maximum < arr[i])
{
index = i;
maximum = arr[i];
}
}
// Use maximum element as a break point
// and merge both subarrays usin simple
// merge function of merge sort
int i = 0, j = n-1;
int[] new_arr = new int[n];
int k = 0;
while (i < index && j > index)
{
if (arr[i] < arr[j])
new_arr[k++] = arr[i++];
else
new_arr[k++] = arr[j--];
}
// Merge remaining elements
while (i < index)
new_arr[k++] = arr[i++];
while (j > index)
new_arr[k++] = arr[j--];
new_arr[n-1] = maximum;
// Modify original array
for (int p = 0; p < n ; p++)
arr[p] = new_arr[p];
}

Sorting array by insertion sort

I'm trying to sort an array using Insertion Sort.
Instead of changing and rearranging elements of array itself, I'm using another array named rank to Map to point to original array.
here is my code
int i,j;
int ar[] = {50,14,51,25,10};
int rank[] = {0,1,2,3,4};
for(i=1 ; i< 5 ; ++i) // second element onwards
{
int temp = rank[i]; // stores current value in temp variable
/**
* temp = 1
* j = 0
*/
j = rank[i] - 1;
while ( ar[temp] < ar[ rank[j] ] && j > -1)
{
rank[j+1] = rank[j]; // move elemnts in map forward
j--;
} // end loop
// insert temp at proper place
rank[j+1] = temp;
}
for(i=0 ; i< 5 ; ++i)
printf("Rank : %d, Number : %d \n",rank[i],ar[i]);
But, it's not giving an expected output. Can anyone point towards what is the mistake in the logic ?
You logic flaw is as following:
At this code section
while ( ar[temp] < ar[ rank[j] ] && j > -1)
{
rank[j+1] = rank[j]; // move elemnts in map forward
j--;
} // end loop
rank[j] means the rank of the value at ar[j].
And when you use ar[rank[j]], you are comparing ar[temp] to the value indexed at "the rank of the value at ar[ j ]", which means you are not comparing to the biggest value in the sorted portion of rank[].
Therefore, you may not get into this loop even if ar[temp] is the second smallest
For example:
So far during loop#2 (i = 2)
ar[] : {50,14,51,25,10};
rank[] : {1,0,2,3,4}; ({1,0} is the sorted portion of rank[])
The 0 only means 14 is the smallest value in {50,14} (the scanned portion of ar[])
AND ar[rank[2]] ( ar[0]) only happens to be the largest value in {50,14} (the scanned portion of ar[]) by coincidence
If this value (ar[rank[2]]) is not the largest, and happens to be smaller than ar[temp], you program will just skip the loop. Even if ar[temp] is smaller than all the other values in ar[]
rank[j+1] = rank[j]
makes no sense. You should swap them.
This was the code I had when took data structures class...
In the while condition it checks V... and inside the loop it moves the elements in V...
In your code you are comparing in one array and moving in the other... if you need the original position of elements you could just copy the array into a new one and sort the new array, instead of creating those ranks... (If you really need those ranks I'm pretty sure you could create while you sort)

Interview - find greater element for each array`s element

I was asked the following question during the interview (Unfortunately I couldn't find the answer better than N^2)
For a given array arr for unsigned int of size N,for each element (in the index i) I should return an element in the index j (j > i),such that arr[j] > arr[i]
I.e. I should return array res in which res[i] has a arr[j],j>i,arr[j] > arr[i],j is min among all indices k ,such that arr[k] > arr[i]
for example
arr[] = {3,1,4,2,5,7};
res[] = {2,2,4,4,5,-1};//-1 says no such index
Any proposition to do it in better time complexity?
Thanks
O(N) Time and O(N) Space Complexity:
Create empty stack, iterate the array from the right
for each iterated item:
keep popping from the stack as long as item on the top is smaller than current, then if the stack becomes empty there's no bigger element on the right, if not that's your first bigger item on the right for current element, push current item on the stack
void GetFirstRight(int* arr, int size, int* res){
stack<int> s;
for (int i = size - 1; i >= 0; --i) {
while (!s.empty() && s.top() <= arr[i]) s.pop();
if (s.empty()) {
res[i] = -1;
} else {
res[i] = s.top();
}
s.push(arr[i]);
}
}
O(n) algorithm:
Maintain a stack of indexes that are still not solved. This will be sorted so that the minimum still unsolved value is on the top. As you reach a new element pop from the stack until the value of the new element is less than the value on top of the stack. For each that you pop, the answer is the current index. Then push on the current index. At the end, the result for anything still on the stack is -1.
Code (C++):
stack<int> unsolved;
int arr[] = {3,1,4,2,5,7}, N = 6;
int res[1234];
int main() {
for (int i = 0; i < N; i++) {
while (!unsolved.empty() && arr[unsolved.top()] < arr[i]) {
res[unsolved.top()] = i;
unsolved.pop();
}
unsolved.push(i);
}
while (!unsolved.empty()) {
res[unsolved.top()] = -1;
unsolved.pop();
}
// Print results
for (int i = 0; i < N; i++) printf("%d%c", res[i], i==N-1 ? '\n' : ' ');
return 0;
}
Output:
2 2 4 4 5 -1
Keep a parallel array b. make b[0]=0.
Make a run to iterate thru the elements of a. as you go along, set the values of b to the differences of consecutive cells of a.
so, if
a[0]=9
a[1]=4
a[2]=17
a[3]=2
a[4]=3
a[5]=6
a[6]=0
a[7]=3
a[8]=1
a[9]=1
a[10]=7
then,
b[0]=0
b[1]=-5
b[2]=13
b[3]=-15
b[4]=1
b[5]=3
b[6]=-6
b[7]=3
b[8]=-2
b[9]=0
b[10]=6
All you should be concerned about is the (-) cells in the b array.
Now, start iterating backwards on array b-- starting from
b[10] in the above eg.
Keep a currentMax value. initially set to the first max (+)
on the array-- nothing you can do about the (-) entries at the end of the array.
As you iterate backwards from b[b.length] down to b[0], do the following:
update currentMax:
currentMax += <value at the current cell of **b**>
if (currentMax<0) then /* you've hit elements-with-no-indexes*/ then keep going till you find a positive b[i] entry, and when you find one, set the value of currentMax to it.
(+) values of currentMax indicate cells that the cell that reset currentMax is the index for all cells visited-so-far, (-) values are no-index cells.
In the above eg, 7 at a[10] is the index of all in a[3]..a[9], because
-currentMax is the one initialized at cell 10 (and not reset afterwards)
-the value of currentMax after all those additions is still (+) all the way up to cell 4 (cell 4 reflects the change from cell 3-to-4)
At b[3], currentMax falls below 0--meaning no index for cell 2.
The value found at b[2] is positive while currentMax is negative-- so make at b[3], currentMax=13 and iterate on.
Linear in the array size-- takes O(n) time.

Resources