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.
Related
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 4 years ago.
Improve this question
I had to solve a problem in a exam. But it couldn't pass all the test cases. It was this equation.
an + bnlog2(n) + cn3 = k where a,b,c,k are given. That position can be max 2^63 -1
suppose the input is
input:
2 1 1 12167000368000
2 1 1 188000000000000
output:
23000
0
this is my solution
#include<stdio.h>
long long Log2n(long long n)
{
return (n > 1)? 1 + Log2n(n/2): 0;
}
int main(){
long long a,b,c,k, pos, flag = 0;
scanf("%lld%lld%lld%lld",&a,&b,&c,&k);
for(int i=0; i<100000000; i++){
pos = a*i + b*i*Log2n(i)+ c*(i*i*i);
if(pos == k){
printf("%lld ",i);
flag = 1;
break;
}
}
if(flag == 0){
printf("0");
}
return 0;
}
like small inputs 2 1 1 36 it's giving the right input. But when the input of k is big size or the number is not this it's not working properly.
I think my iteration has a problem. How many times this iteration should go on? or is there any better solution to find this n value?
Note that a*i + b*i*Log2n(i)+ c*i*i*i is mostly the same as (a + b*Log2n(i)+ c*i*i) * i.
This means (to reduce the risk of overflow) you can do:
if(k % i == 0) {
pos_divi = a + b*Log2n(i)+ c*i*i;
if(pos_divi == k / i) {
printf("%lld ",i);
flag = 1;
break;
}
}
Since i is declared as int, (i*i*i) will overflow and invoke undefined behaviour.
You should declare i as long longor cast i to long long in the calculation of pos.
for(int i=0; i<100000000; i++)
should be
for(long long i=0; i<100000000; i++)
The limit 100000000 seems a little bit arbitrary and should be adjusted, since even with long long there can be overflows.
The change to long long of course is no general solution, but will work for the test case. The type which should be used heavily depends on the domain of the input variables.
I suppose that k > 0
We search fo n such as n^3(a/n^2 + b log2(n)/n^2 + c)= k
It is necessary to treat several cases according to that c> 0, c = 0, c <0
I leave the case c = 0 for which we would factorize rather by nlog2(n)
Suppose c>0. As lim |a/n^2| = 0 (n-> +oo) and lim |b log2(n)/n^2| = 0 (n-> +oo)
there exists p such as for n>p, |a/n^2| < c/4 and |b log2(n)/n^2| < c/4
we can search programmatically for such an integer p
so -c/4 < a/n^2 < c/4 and -c/4 < blog2(n)/n^2 < c/4
Thus for n>p, n^3*c/2 <= k <= n^3*3*c/2 and then 2k/(3c) <= n^3 <= 2k / c
which simplifies the search for n ...
If c < 0 we can make a loop by incrementing n and comparing the left member with k and stopping when this member becomes negative.
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
my task is to write the code to a heapsort according to pseudo code. It should heapsort the input Array (4 3 2 5 6 7 8 9 12 1) and then print it with the printHeap method. I know for a fact that the printHeap works, because I have already used it with a method called buildHeap (to build max heap binary trees, but you all already know that :)) and there it works flawlessly, so my problem lies in heapSort.
It sorts correctly and prints it in the way it's supposed to (parent -- child 1, parent -- 2, etc.), only issue is, that the biggest and last value, which is 12, suddenly turns into 24 and I have no clue why.
The code is the following:
void heapSort(int a[], int n){
int x = n+1;
int i;
int temp;
buildMaxHeap(a, n);
for (i = n; i >= 1; i--){
temp = a[i];
a[i] = a [0];
a [0] = temp;
x--;
heapify(a, 0, x);
}
void printHeap(int a[], int n){
int i;
printf("graph g { \n");
for (i = 0; i < n/2; i++){
printf("%d -- %d\n", a[i], a[left(i)]);
if (right(i) < n){
printf("%d -- %d\n", a[i], a[right(i)]);
}
}
printf("}\n");
Output is following:
1 2 3 4 5 6 7 8 9 24
graph g {
1 -- 2
1 -- 3
2 -- 4
2 -- 5
3 -- 6
3 -- 7
4 -- 8
4 -- 9
5 -- 24
}
just so you know what exactly I have done, I will attach the while .c file here:
https://onedrive.live.com/redir?resid=8BC629F201D2BC63!26268&authkey=!AFqVlm9AptiZ_xM&ithint=file%2cc
Really grateful for your help!
Cheers
Arik
Well, you observe an undefined behavior. (I personally on an online IDE got 0 instead of the 12(24).)
Try:
void heapSort(int a[], int n)
{
int x = n; /* changed from n+1 */
int i;
int temp;
buildMaxHeap(a, n);
for (i = n-1; i >= 0; i--){ /*<-- changed*/
temp = a[i];
a[i] = a[0];
a[0] = temp;
x--;
heapify(a, 0, x);
}
}
Your arrays in almost all general purpose languages of today start with index 0[For thorough information see wiki.] You loop your array for (i = n; i >= 1; i--) wrongly and since the heap is max, don't process the first element and go out of bounds with the last. Although arithmetic with the nth element is defined in the standard, it is not meant so rather < n and some pointer work.
On a side note, you can use macros (#defines) for the left, right etc. functions to improve performance and ease the reading.
I hope that saves the day and the AlgoDat Exercise.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
There are n balls each with a particular weight and cost. The balls have to be removed such that the cost of the balls removed is maximum. An additional condition is that the sum of weights of the last k balls should be <= the weight of the the remaining balls multiplied by another constant Q (k is a constant: given). The balls can only be removed from the ends. How can the cost be maximised. I can solve this question using a recursive algorithm. But I would like to know how to reduce the complexity O(n) using queues.
#include<stdio.h>
long int Q, val[100000], wt[100000],k,n;
long int steal(long int l,long int r,long int cut)
{
long int i,sum,steal1, steal2 ,X, Y = 0;
for(i = r; i > r - k; i--)
Y = Y + wt[i];
sum = 0;
for(i = l; i <= r; i++)
sum = sum + wt[i];
X = sum - Y;
if(X * Q < Y)
return 0;
else
{
steal1 = steal(l, r-1, r);
steal2 = steal(l+1, r, l);
if(steal1 == 0 && steal2 != 0)
return steal2 ;
else if(steal1 != 0 && steal2 == 0)
return steal1 ;
else if(steal1 == 0 && steal2 == 0)
{
if(r-l+1 == n)
return 0;
else
return val[cut];
}
else
{
if(steal1+val[r] > steal2+val[l])
return steal1+val[r];
else
return steal2+val[l];
}
}
}
int main()
{
long int i;
scanf("%ld %ld %ld", &n, &k, &Q);
for(i = 0; i < n; i++)
scanf("%ld", &wt[i]);
for(i = 0; i < n; i++)
scanf("%ld", &val[i]);
printf("%ld\n", steal(0, n - 1,n));
return 0;
}
Test Case :
5 2 1 (n, k and q respectively)
5 4 6 3 2 (weights of the n balls)
3 2 4 2 2 (Value of each ball)
Answer : 5
Things to be fixed:
You have some arrays declared with 100000 elements, regardless of the actual value of n, which should be their size instead. If 100000 < n, then the arrays are too small and you will have problems due to index out of bounds. If n < 100000, then you waste a lot of memory. Instead of initializing arrays with 100000 element, initialize them with n elements. Read this for further info.
You could use insertion sort while reading the input, to sort the elements by weight, value, or some formula, so you will be able to differentiate balls by weight, or value, or some formula which suits your needs better.
With recursion you are using the stack. You could use a custom stack for that purpose.
If you want to queue the balls, then the queue can be the one created at 2.
If you want the very best solution, then you will need to implement Divide et Impera for your purpose.
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 7 years ago.
Improve this question
i'm a beginner c programmer studying computer science and i'm trying to create a sorting program to sort an array of integers although i keep getting wrong results, this is what i got so far:
#include <stdio.h>
#include <string.h>
#define TAM 9
int sort_array(int num1[],int num2[]);
int main(){
int i=0;
int num1[TAM] = {5,6,2,4,7,1,3,0};
int num2[TAM] = {0};
int * ptr_num2 = num2;
sort_array(num1,num2);
while(*ptr_num2 != '\0'){
printf("%c",*ptr_num2+48);
ptr_num2++;
}
putchar('\n');
return 0;
}
int sort_array(int num1[],int num2[]){
int min=256,max=0,i,j;
int * ptr_num1 = num1;
int * ptr_max = num1;
int * ptr_num2 = num2;
/* check for max */
while(*ptr_max != '\0'){
if(*ptr_max > max) max = *ptr_max;
ptr_max++;
}
for(i=0;i<TAM-1;i++){
/* check for min */
for(j=0;j<TAM-1;j++){
if(*ptr_num1 < min) min = *ptr_num1;
ptr_num1++;
num1[i] = max;
}
*ptr_num2 = min;
ptr_num2++;
}
return 0;
}
I've been banging my head for several hours on this already.
EDIT: Forgot to mention that some of these things might not make sense since i'm just experimenting with a few things.
I understand you do not know about the typical array sorts... Well, let me to introduce you to one of the more simple ones. Allthough it's usually not the most efficient one, it's the easiest one to understand, and considering the fact you are messing with little arrays and not databases, it will be just fine.
I am talking about good old Chum, our Bubble sort.
Bubble sort is a well known simple array sorting algorithm -
The logic is simple. You go over the whole array on pairs of two - I.e, Array[0] with Array[1], Array[1] with Array[2], etc...
Whenever you find that things are not the way they are supposed to be - in your case, The larger index number is bigger than the lower index number - you swap between them, until you reach an iteration where you passed through the whole array and didnt swap at all.
In case you didn't understand well, here's Pseudo code from wikipedia (OMG who the heck uses wikipedia i'm such a n00b):
procedure bubbleSort( A : list of sortable items )
n = length(A)
repeat
swapped = false
for i = 1 to n-1 inclusive do
/* if this pair is out of order */
if A[i-1] > A[i] then
/* swap them and remember something changed */
swap( A[i-1], A[i] )
swapped = true
end if
end for
until not swapped
end procedure
And here's some C code:
#include <stdio.h>
int main()
{
int array[100], n, c, d, swap;
printf("Enter number of elements\n");
scanf("%d", &n);
printf("Enter %d integers\n", n);
for (c = 0; c < n; c++)
scanf("%d", &array[c]);
for (c = 0 ; c < ( n - 1 ); c++)
{
for (d = 0 ; d < n - c - 1; d++)
{
if (array[d] > array[d+1]) /* For decreasing order use < */
{
swap = array[d];
array[d] = array[d+1];
array[d+1] = swap;
}
}
}
printf("Sorted list in ascending order:\n");
for ( c = 0 ; c < n ; c++ )
printf("%d\n", array[c]);
return 0;
}
Here again, btw, the credit is not for me:
http://www.programmingsimplified.com/c/source-code/c-program-bubble-sort
Hope this helped you, and good luck :)
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 7 years ago.
Improve this question
The language is ANSI C. I have 2 arrays of int: A and B. A has an index called m and B an index called n. The assignment says that m MUST BE different from n, so the arrays must have different size. I have coded already this. A is ordered ascending while B is ordered descending. I have to write a function that does the mathematical union of the two arrays in another one called C. If an element is in both the arrays you have to put only one in the array of the union (array C).
My code does not work very well. The last element is not ordered, I receive an output with a very big last number that I do not know from where it comes.
int index_c=index_m+index_n; //the index of array c
// is obtained by the sum of two indexes of the array A and B
int c[index_c];
int k=0;
for (i=0; i < index_m; i++)
{
for (j=0; j < index_n; j++)
{
if (a[i]==b[j])
{
c[k]=a[i]; //put only one time if is repeated more time in the two arrays
}
else
{
c[k]=a[i]; //put the a[i] element in the array c
c[k+1]=b[j]; //the element of the other array next to
}
}
k++;
}
printf("Elements in array C are: \n");
for (i=0; i<index_c; i++)
printf("element %d\n", c[i]);
It doesn't matter if the array C is not sorted, I will sort after the union. Any suggestions?
I am trying the suggestion of put k++ when I add 1 input, and k+2 when I add two input to array C. Now It works a bit well, but it doesn't full work. I mean in output I have not big number values but one of the output value (the 3rd) is the same as the first.
Example: 3 9 3 2 5 The second 3 is wrong and it's missing a number that is covered by the second 3.
Other example 2 4 2 1 9
I spot two immediate logical errors which should be fixed at the very least:
you either store one number in c, when both inputs are the same, and increase k by 1, or you store two numbers into c. You should then increase k with 2 as well. In the code you have now, you only have to add another +1 -- but consider putting these additions inside the if..else test blocks for clarity. Currently, you are overwriting the last one stored.
You print the result from 0 to index_c, the sum of the lengths of the two input arrays. That is not logical because you are throwing out numbers. Hence you get 'random' numbers as output; those are merely uninitialized, i.e. never written to. Print from 0 to k, as that is the valid range of your input.
So far none of the answers exploit the fact that the arrays are both sorted. Here is an implementation which is almost identical to a merge as suggested in the comments. The complexity of the merge is O(m + n).
I have assumed that each array has no duplicates (no [0, 1, 1, 3]), but you could add checks like if (k == 0 || k > 0 && C[k - 1] != A[i]) to fix this if I assumed wrong.
The function returns the length of C.C is sorted in increasing order. To have C be sorted in decreasing order instead change if (A[i] < B[j]) to if (A[i] > B[j]).
int union_merge(const int *A, int m, const int *B, int n, int *C) {
int i = 0, j = n - 1, k = 0;
while (i < m && j >= 0) {
if (A[i] < B[j]) {
C[k++] = A[i++];
} else if (A[i] == B[j]) {
C[k++] = A[i++];
--j;
} else {
C[k++] = B[j--];
}
}
while (j >= 0) {
C[k++] = B[j--];
}
while (i < m) {
C[k++] = A[i++];
}
return k;
}
Let's say that you have two arrays A and B, and union array C. You can input both arrays A and B into one array. Then you can sort that array and after sorting iterate over array and add value to array C(union array) if you didn't already add that value.Total complexity is O( N * log(N) ) Look at code:
#include <stdio.h>
#include <stdlib.h>
#define MAX 100000
int a[2*MAX+3], c[2*MAX+3];
int cmp(const void *a, const void *b) {
if ( *(int*)a < *(int*)b ) return -1;
if ( *(int*)a == *(int*)b ) return 0;
if ( *(int*)a > *(int*)b ) return 1;
}
int main() {
int i, k;
int n, m; scanf("%d%d", &n, &m); // size of the first array and size of the second array
n += m;
for(i = 0; i < n; ++i) // O(N) , input both arrays into one array
scanf("%d", &a[i]);
qsort(a, n, sizeof(int), cmp); // O( N * log(N) ), sort the given array
c[0] = a[0];
for(i = 1, k = 1; i < n; ++i) // O(N)
if(c[k - 1] != a[i]) // if the last element that you added to the union array is different than the current element in first array then add that element to union array
c[k++] = a[i];
for(i = 0; i < k; ++i) // O(K)
printf("%d ", c[i]);
return 0;
}