Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I encountered this problem at a coding challenge and was not able to solve it. This is the problem statement:
Given an array of transaction costs t, return an array of expected costs e such that it is 0 if product of all transaction costs in t except e[i] is even, else it is 1(i.e for any element in t[i], find product of all elements of t except t[i]. If that product is even, result for that t[i] is 0 else 1).
For example t = [1, 2, 3, 4], e = [ 0, 0, 0, 0]
Explanation: for t, all products are even:[24, 12, 8, 6]
Constraint: do it in O(n) and without division.
FYI, I did it in O(N^2) but couldn't solve it in O(N)
My solution:
int[] arr = {1, 2, 3, 4};
int[] res = new int[arr.length];
for(int i = 0; i < arr.length; i++){
int prd = 1;
for(int j = 0; j < arr.length; j++){
if(i == j) {
continue;
}
prd *= arr[j];
}
if((prd & 1) == 0){
res[i] = 0;
}else {
res[i] = 1;
}
}
You don't need division; all you need is a simple odd/even check. However you care to do this is fine; for instance, mask off everything but the final bit.
Very simply, if all elements are odd, then e is a vector of 1's. If one element is even, e is a vector of all 0's except for that one position, which is a 1. If more than one element is even, then e is a vector of 0's.
This requires a single pass through t (which is O(N)) to find the quantity of even elements; then you can generate e in O(N) time
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
#define SIZE 10
void fun(int arr[]){
int i,k,j,n = SIZE;
k = 0;
for (i = 1 ; i < SIZE; i++) {
j = k;
while (j > 0 && arr[j] != arr[i])
j = j - 1;
if( j == 0){
k = k + 1;
arr[k] = arr[i];
}
else
n--;
}
}
This function was in my test today.
My question is: does someone know what it does?
What does the variable n represent at the end of the function?
At the end of the function, the variable n will have counted how many times each i-th array value in the range [0, SIZE) was unique among the first i array elements..
In addition, the first n elements of the array will contain exactly those elements that were found to be unique in the above sense. All other array entries will remain unchanged.
The other variables will have the following values:
i == SIZE
j == some value between [0, SIZE)
k == n-1
Some inline comments may help understand the code better.
#define SIZE 10
void fun(int arr[]){
int i,k,j,n = SIZE;
k = 0;
// walk through the array up until its 10th element, skipping
// the first entry and hoping that the array actually contains
// at least 10 entries
for (i = 1 ; i < SIZE; i++) {
// similar to i, the variable k also walks up towards 10.
// However it starts at 0, not at 1, and it does not
// necessarily get incremented in every loop iteration. More
// on that below.
// Here, we set the variable j to start out as the same value
// as the current k, but j will walk the opposite direction, i.e.,
// toward 0, not toward 10.
j = k;
// find the largest j in the open interval [0,k) for which
// the array entry arr[j] differs from the current arr[i]
while (j > 0 && arr[j] != arr[i])
j = j - 1;
// if no value in [0, k) was equal to arr[i], we'll end up \
// with j == 0
if( j == 0){
// then we increment k -- that is, k counts how many times
// we encountered a value arr[i] during the for-loop that was
// unique among the first i array entries. But since the
// for loop starts at 1 instead of 0, k will count one
// element too few.
k = k + 1;
// well, so much for 'unique': here, we actually copy the current
// value arr[i] into arr[k]
arr[k] = arr[i];
}
else
// this part in effect assures that the expression
// (n-k) gets decremented in every iteration of the loop,
// no matter if j == 0 is true or false.
// Since we start out with (n-k) = SIZE, and
// the loop body gets executed SIZE-1 times, (n-k) will
// be equal to 1 after the for-loop has terminated.
n--;
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
This is a problem a friend of mine gave me as a challenge. I've managed to come up with a recursive algorithm that works fine for small inputs, however I get segmentation faults for large values. I suppose that's because of a stack overflow. I use the C language for solving the problem.
You are given an array of n numbers. Find and print the maximum length of the subset such that for any two numbers form that subset, the sum of the numbers is not divisible by k.
Input contains on the first line 2 numbers n and k, on the next line there are n numbers a[i] such that:
1 <= n <= 10^5
0 <= a[i] <= 10^9
1 <= k <= 100
# Example input:
4 3
1 7 4 2
# Output:
3
Explanation: (1 7 4) 1 + 7 = 8; 1 + 4 = 5; 7 + 4 = 11; all of them non-divisible by 3.
My solution is based on the following idea: For all numbers in the array check the sum with the others if it is divisible by k. If we find a match then create 2 arrays, one excluding the first term of the sum and one excluding the second one, this way we exclude such pairs from our subsets. Then do the same thing we did to the first array to both of them. If we have checked all the elements from the the array then set the solution to the length of the array and continue applying the "solver" to only the arrays that have a length greater than the solution already found. This algorithm works well for n < 47 , more than that and it gives me a seg fault. I would like to see any solution that solves the problem.
#include <stdio.h>
int n, k;
int * deleteElement(int * a, int n, int j){
int *c = (int*) malloc((n-1) * sizeof(int));
int k = 0;
for(int i = 0; i < n; i++){
if(i == j) continue;
c[k] = a[i];
k++;
}
return c;
}
int sol = 0;
void solver(int *a, int n, int *sol){
int *b, *c;
if(n <= *sol) return;
for(int i = 0; i < n-1; i++){
for(int j = i + 1; j < n; j++){
if((a[i] + a[j]) % k == 0){
c = deleteElement(a, n, i);
b = deleteElement(a, n, j);
solver(c, n-1, sol);
solver(b, n-1, sol);
return;
}
}
}
*sol = n;
}
int main(){
scanf("%d", &n);
scanf("%d", &k);
int a[n];
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
solver(a, n, &sol);
printf("%d\n", sol);
return 0;
}
You could use iteration to get rid of one of your two recursive calls, but that wouldn't help with stack space, since they have the same depth -- one call is as bad as 2.
It's easy enough to write a completely iterative algorithm that actually tests all the valid sets, but that's still an exponential time algorithm. In any case that this would save you from a stack overflow, it would take way too long to run. Since that algorithm would also suck, I don't want to write it.
A reasonable linear-time way to solve this problem is:
Calculate a map MODCOUNTS where MODCOUNTS[m] = the number of elements x such that x%k == m
Since any valid subset can only have one element divisible by k, if MODCOUNTS[0] > 1, then set MODCOUNTS[0]=1
Similarly, if k is even, and MODCOUNTS[k/2] > 1, then set MODCOUNTS[k/2]=1
Now, add up all the values in MODCOUNTS, but leave out a value MODCOUNTS[i] if:
i > 0, i*2 < k, AND MODCOUNTS[i] < MODCOUNTS[k-i]; OR
i*2 > k AND MODCOUNTS[i] <= MODCOUNTS[k-i]
rule 4 reflects that fact that a valid subset cannot include any elements x and y such that (x+y)%k = 0, for the cases that we didn't take care of in rules 2 and 3. The biggest valid subset includes all the elements from in MODCOUNTS[i], or all the elements in MODCOUNTS[k-i], but not elements from both.
If you use sparse data structure like a hash table to implement MODCOUNTS, then the whole thing takes O(N) time.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I try to do a function in order to sort an array and display after that only the prime number. But all the elements of my array are random numbers, and the problem is that the function display only negative prime numbers and not positive like 7 and 3, what can I do in order to solve the problem
int prime_arr(int size, int *arr, int *sort_arr)
{
int i, j, k = 0, flag;
for (i = 0; i < size; i++)
{
flag = 0;
for (j = 2; j < arr[i]/2; j++)
{
if (arr[i] % j == 0){
flag = 1;
break;
}
}
if (flag == 0){
sort_arr[k++] = arr[i];
}
}
return j;
}
I see 3 problems with the code:
1. You should return k, not j. k is the size of sort_arr
2. You should loop until arr[i] / 2, not one less than that (see <= in code below)
3. You do not handle negative numbers. Change your loop to the following:
for (j = 2; j <= abs(arr[i])/2; j++)
Without the code that prints your values, I'm not sure exactly what you're looking for, but hopefully fixing these will fix your problem.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
Given the problem:
The statement is a bit ambiguous. I don't really understand what they want.
I can display the desired result using just a regular for loop:
int step = 0
for(int i = 1; i < m + 1; i++)
{
if(i != p)
{
printf("(%d, %d)", step, i);
step++;
}
}
Is this what they really want? I see that they are talking about linear time, so I think it can't be that easy? Am I supposed to build the vector that they are talking about, and then delete it?
Something like this? (compile with gcc test.c -lm)
#include <stdio.h>
#include <math.h>
int main(void) {
int i, j;
int n = 4;
int m = (int)pow(2,n);
int p = 5;
for(i = 1; i <= n; i++)
{
for(j = (int)pow(2,i-1); j < ((int)pow(2,i)); j++)
{
if(j == p) {
continue;
}
printf("%d, %d\n", i, j);
// remove vector[j]
if((j == (m-1)) && (m != p)) {
printf("%d, %d\n", i, m);
// remove vector[m]
}
}
}
return 0;
}
Run result n=3, p=5:
1, 1
2, 2
2, 3
3, 4
3, 6
3, 7
3, 8
Run result n=4, p=5:
1, 1
2, 2
2, 3
3, 4
3, 6
3, 7
4, 8
4, 9
4, 10
4, 11
4, 12
4, 13
4, 14
4, 15
4, 16
You should write the full code. Let me make it simple:
It should delete every element of the array.
By the end of the loop your program should print out the step and one of the numbers that were deleted, into the format (k, q) where k is the step you are on, and q is one of the elements you had deleted .
Every time you delete an element you can change it by X.
You also need to remember the algorithm they are telling you to use and the "rules of the game", for example: n should be positive and an integer.
And if you do not understand the algorithm, just try to put the idea on a paper:
When I put n = 1, I should delete one element from the array. When n = 2, 2 elements, When n = 3 it should delete 4 elements , n = 4 it deletes 8 element, etc.
As we can see, it is pretty simple because it goes like a geometric progression.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Given an array of integers, A, and an integer value, K, create array B where B[i] is the minimum value in the sub-array A[i], A[i+1], ..., A[i+K-1]. Note that B.length will be equal to A.length - K.
For example for K = 3 and A=[1,2,3,4,0,1,2] the solution is B=[1,2,0,0,0].
A = [1,2,3,4,0,1,2]
_____| | | | |
B[1] = 1 | | | |
_____| | | |
B[2] = 2 | | |
_____| | |
B[3] = 0 | |
_____| |
B[4] = 0 |
_____|
B[5] = 0
A solution for O(kn) time complexity is as follows:
public static int[] createArray(int[] arr, int k) {
int[] result = new int[arr.length];
for (int i = 0; i <= arr.length - k; i++) {
int curSmallestVal = arr[i];
for (int j = i + 1; j < i + k; j++) {
curSmallestVal = Math.min(curSmallestVal, arr[j]);
}
result[i] = curSmallestVal;
}
return result;
}
Can you provide a more elegant solution with O(n) runtime? (potentially with using queues)
Update with the O(n) solution:
public static int[] getMinSlidingWindow(int[] arr, int k) {
int[] result = new int[arr.length-k+1];
Deque<Integer> queue = new LinkedList<Integer>();
//initialize sliding window
for (int i = 0; i < k; i++) {
if (!queue.isEmpty() && arr[queue.getLast()] >= arr[i])
queue.removeLast();
queue.addLast(i);
}
for (int i = k; i < arr.length; i++) {
result[i-k] = arr[queue.getFirst()];
while (!queue.isEmpty() && arr[queue.getLast()] >= arr[i])
queue.removeLast();
queue.addLast(i);
while (!queue.isEmpty() && queue.getFirst() <= i-k)
queue.removeFirst();
}
result[arr.length-k] = arr[queue.removeFirst()];
return result;
}
It is possible to achieve O(n) time complexity using standard sliding window minimum algorithm with a deque. Here is it's detailed description: http://people.cs.uct.ac.za/~ksmith/articles/sliding_window_minimum.html
Using a double ended queue (one that supports adding pushing and poppoing from the front and the back) with a bit of extra logic you can construct a solution that runs O(n).
Here's the pseudocode for a solution.
void getMaxSlidingWindow(int[] A, int k) {
int[] B = new int[A.length - k];
// Store the indexes of A in Q
// Q.front(): index of smallest element in the window, Q.back(): index of the largest one in the window
DobuleEndedQueue<int> Q = new DobuleEndedQueue<int>();
for(int i=0; i<k; i++) {
// Fill up the double ended queue for the first k elements
// Remove elements that we would ignore because they're bigger than the next one in the window
while(!Q.empty() && A[i] <= A[Q.back()]) {
Q.popBack();
}
Q.pushBack(i);
}
for(int i=k; i < A.length; i++) {
B[i - k] = A[Q.front()]; // The first element in the queue is the index of the smallest element in the window
// Add the current element to the queue. Before we do, remove all elements that we would ignore immediately because they're bigger than the current one
while(!Q.empty() && A[i] <= A[Q.back()] ) {
Q.popBack();
}
Q.pushToBack(i);
// Remove any index from the front of the queue which is no longer in the window
while(!Q.empty() && Q.front() <= i-k) {
Q.popFront();
}
}
B[A.length - k] = A[Q.front()];
}
The time complexity of this solution is O(n): we iterate through all elements once and either add or remove them to the double ended queue once. The maximum operations done are 2n, which is a O(n) complexity.
For this solution to work you need to implement the double ended queue data structure with the following operations:
class DobuleEndedQueue
int front(), void pushFront(int n), void popFront() // peeks at the front element, adds and removes to the front
int back(), void pushBack(int n) , void popBack() // same for the back element
Further explanation for the algorithm with a simple example:
Iterate through the first k elements and insert these as indexes into a double ended Q data structure so that A[Q.front()] is the smallest element and A[Q.back()] is the largest element in the window.
As we build up the window, throw out "unnecessary" elements from this queue: both smallest elements that would not be counted and elements which are outside of the window
Example of building the queue for A=[8, 6, 9, 2] and k-3
Q = [0], (Insert 0 to the back of Q because A[0] is the smallest element we've seen.)
Q = [1], (A[1] < Q.back() so pop the back element and replace it with 1. We do this because A[0] will be irrelevant when looking for the smallest number from now on.)
Q = [1, 2], B=[8] (A[2] is > Q.back(), so we just add 2 on to the Q. B[0] will be the smallest item in Q, which is A[Q.first()], that is A[1])
Q = [3], B=[8, 2] (A[4] is smaller than all elements in Q, so we pop all of them. B[1] will be the smallest item in Q, A[Q.first()], that is A[3]
First idea that comes to my mind is using two sets. Both sets store std::pair<index_t,value_t> but have different ordering. (one is ordered by index and one by value). This way you can at each step iterating trough array find minimum (first element in set ordered by values) and what element/pair to remove from both sets (first element in set ordered by index) . At each step you add pair in each set and remove pair from each set.