I want to find the longest increasing subsequence without sorting it, and to then sum the numbers of the period, for example like :
12, 15, 16, 4, 7, 10, 20,25
12,15,16 is an increasing subsequence.
4,7,10,20 is another increasing subsequence.
but since 4,7,10,20,25 are 5 elements and 12,15,16 are 3 which is less than the 4, the output should be the sum of the longer period which is the sum of the 5 elements, 66.
How could such a thing be done using c?
I am new to C so this is all what I could think of.
#include<stdio.h>
int main() {
int count = 0;
int n;
int max = 0;
scanf("%d", &n);
int arr[1000];
for(int i = 0;i<n;i++){
if(arr[i+1>arr[i])
count++;
if(count>max)
max = count;
}
You really need two loops.
One that iterates through all elements. This is the "starting" index of a sequence.
Then, an inner loop that starts at one element to the right of the start. It loops to the end of the array but stops if it sees the current element is out of sequence.
After the second loop ends, the difference of these two indexes is the sequence length.
Here is some refactored code. It is annotated:
#include <stdio.h>
int arr[] = { 17, 18, 19, 5, 6, 23, 24, 25, 24, 25, 17, 18, 19 };
// show -- print a sequence
void
show(int begidx,int count,const char *tag)
{
printf("%s: %d %d --",tag,begidx,count);
for (; count > 0; --count, ++begidx)
printf(" %d",arr[begidx]);
printf("\n");
}
// sum -- get sum of the sequence
int
sum(int begidx,int count)
{
int sum = 0;
for (; count > 0; --count, ++begidx)
sum += arr[begidx];
return sum;
}
int
main(void)
{
int count = sizeof(arr) / sizeof(arr[0]);
int maxlen = 0;
int maxidx = -1;
show(0,count,"ORIG");
// loop through all possible starting points for sequence
for (int ilhs = 0; ilhs < count; ++ilhs) {
int lval = arr[ilhs];
// loop through all numbers to the right of the starter
// stop at the array end or when we get a number that is out of sequence
int irhs;
for (irhs = ilhs + 1; irhs < count; ++irhs) {
int rval = arr[irhs];
// out of sequence -- we've hit the end
if (rval < lval)
break;
lval = rval;
}
// get length of the sequence we just saw
int curlen = irhs - ilhs;
// remember a larger sequence
if (curlen > maxlen) {
maxlen = curlen;
maxidx = ilhs;
show(maxidx,maxlen,"NEW");
}
}
// show the maximum sequence
show(maxidx,maxlen,"FINAL");
// sum the sequence
printf("SUM: %d\n",sum(maxidx,maxlen));
return 0;
}
Here is the program output:
ORIG: 0 13 -- 17 18 19 5 6 23 24 25 24 25 17 18 19
NEW: 0 3 -- 17 18 19
NEW: 3 5 -- 5 6 23 24 25
FINAL: 3 5 -- 5 6 23 24 25
SUM: 83
UPDATE:
A [considerable] speedup for the above is to change:
for (int ilhs = 0; ilhs < count; ++ilhs) {
Into:
for (int ilhs = 0; ilhs < count; ilhs = irhs) {
And, move the int irhs; above the outer loop.
This reduces the time from O(n^2) to O(n)
Here's an outline of one possible algorithm that will solve it using one loop.
Building blocks:
A variable that stores the number of elements in the longest sequence encountered so far, let's call it longest_seq.
A variable that stores the sum of the longest sequence encountered so far, longest_sum.
A variable for counting the length of the sequence you are currently examining, running_seq.
A variable keeping the sum of the current sequence, running_sum.
Start by initializing:
longest_seq = 0
longest_sum = 0
Then initialize the running variables to handle the first element. The way the following loop is created should make it clear why.
running_seq = 1
running_sum = arr[0]
Now to the interesting part:
Let an index variable, i, loop from 1 (not 0 as usual, we handled the first element before the loop) to the number of elements you have in arr, minus 1.
If arr[i] is greater than arr[i-1] (the previous element), the running sequence is still going on, so
Increase running_seq by 1.
else, if arr[i] is not greater than arr[i-1], the running sequence is broken, so
Check if running_seq is greater than longest_seq. If it is:
Save running_seq and running_sum to longest_seq and longest_sum.
Reset running_seq = 1 and running_sum = 0.
Unconditionally add arr[i] to running_sum
When the loop is done, you need to check if running_seq is greater than longest_seq again (and save the values in case it is) just in case the longest sequence happened to be at the end of the array.
The answers when this is done are in longest_seq and longest_sum.
Demo implementation
A variant with a minor difference is to change the loop slightly with regards to the updating of running_sum:
Let an index variable, i, loop from 1 (not 0 as usual, we handled the first element before the loop) to the number of elements you have in arr, minus 1.
If arr[i] is greater than arr[i-1] (the previous element), the running sequence is still going on, so
Increase running_seq by 1.
Add arr[i] to running_sum
else, if arr[i] is not greater than arr[i-1], the running sequence is broken, so
Check if running_seq is greater than longest_seq. If it is:
Save running_seq and running_sum to longest_seq and longest_sum.
Reset running_seq = 1 and running_sum = arr[i].
Demo implementation
Related
I came across a problem:
Given an array, find the max count of this array, where count for an element in the array is defined as the no. of elements from this array which can divide this element.
Example: max count from the array [2,2,2,5,6,8,9,9] is 4 as 6 or 8 can be divided by 2,2,2 and by themselves.
My approach is:
Sort the array.
Make a set from this array (in a way such that even this set is sorted in non-descending order).
Take another array in which the array indices are initialized to the no. of times an element appears in the original array. Example: in above example element '2' comes three times, hence index '2-1' in this new array will be initialized to 3, index '9-1' will be initialized to 2 as '9' comes 2 times in this array.
Using two loops I am checking the divisibility of largest (moving largest to smallest) element in the set with smallest (moving smallest to largest) element of the set.
Conditions
1 <= arr[i] <= 10000
1 <= i <= 10000
#include <stdio.h>
#include <stdlib.h>
#include<limits.h>
int cmp(const void *a, const void *b)
{
return (*(int*)a - *(int*)b);
}
void arr_2_set(int *arr, int arr_size,int *set, int *len)
{
int index = 0;
int set_len = 0;
int ele = INT_MIN;
qsort(arr,arr_size,sizeof(int),cmp);
while(index < arr_size)
{
if(ele != arr[index])
{
ele = arr[index];
set[set_len] = ele;
set_len++;
}
index++;
}
*len = set_len;
}
int main(void)
{
int arr[]={2,2,2,5,6,8,9,9}; //array is already sorted in this case
int size = sizeof(arr)/sizeof(arr[0]);
int set[size];
int index = 0;
int set_len = 0;
arr_2_set(arr, size, set, &set_len); //convert array to set - "set_len" is actual length of set
int rev = set_len-1; //this will point to the largest element of set and move towards smaller element
int a[100000] = {[0 ... 99999] = 0}; //new array for keeping the count
while(index<size)
{
a[arr[index] -1]++;
index++;
}
int half;
int max=INT_MIN;
printf("set len =%d\n\n",set_len);
for(;rev>=0;rev--)
{
index = 0;
half = set[rev]/2;
while(set[index] <= half)
{
if(set[rev]%set[index] == 0)
{
a[set[rev] -1] += a[set[index]-1]; //if there are 3 twos, then 3 should be added to count of 8
//printf("index =%d rev =%d set[index] =%d set[rev] =%d count = %d\n",index,rev,set[index],set[rev],a[set[rev] -1]);
}
if(max < a[set[rev]-1])
max = a[set[rev]-1];
index++;
}
}
printf("%d",max);
return 0;
}
Now my question is how can I speed up this program? I was able to pass 9/10 test cases - for the 10th test case (which was hidden), it was showing "Time Limit Exceeded".
For creating a set and finding the count - use a single while loop, when the size of array is big then using a single loop will matter a lot.
In the later half section where two nested loops are there - don't go from largest to smallest element. Go from smallest to largest element while checking which largest element with index lower than the current element can divide this element, add the count of that element to the current element's count (using set[i]/2 logic will still hold here). This way you'll avoid a lot of divisions. Example: if set is {2,3,4,8} in this case, lets say your current position is 8 then you go down till largest element smaller than or equal to 8 which can divide 8 and add it's count to current element's (8) count.
for the 10th test case (which was hidden), it was showing "Time Limit Exceeded".
That may suggest a more time efficient algorithm is expected.
The posted one, first sorts the array (using qsort) and then copies only the unique values into another array, set.
Given the constraints on the possible values, it may be cheaper to implement a counting sort algorithm.
The last part, which searches the maximum number of dividends, can then be implemented as a sieve, using an additional array.
#include <stdio.h>
enum constraints {
MAX_VALUE = 10000
};
int count_dividends(size_t n, int const *arr)
{
// The actual maximum value in the array will be used as a limit.
int maxv = 0;
int counts[MAX_VALUE + 1] = {0};
for (size_t i = 0; i < n; ++i)
{
if ( counts[arr[i]] == 0 && arr[i] > maxv )
{
maxv = arr[i];
}
++counts[arr[i]];
}
// Now, instead of searching for the dividends of an element, it
// adds the number of factors to each multiple.
// So, say there are two elements of value 3, it adds 2 to all
// the multiples of 3 in the total array.
int totals[MAX_VALUE + 1] = {0};
int count = 0;
// It starts from 2, it will add the numbers of 1's once, at the end.
for (int i = 2; i <= maxv; ++i)
{
// It always skips the values that weren't in the original array.
if ( counts[i] != 0 )
{
for ( int j = 2 * i; j <= maxv; j += i)
{
if ( counts[j] != 0 )
totals[j] += counts[i];
}
if ( counts[i] + totals[i] > count )
{
count = counts[i] + totals[i];
}
}
}
return count + counts[1];
}
int main(void)
{
{
int a[] = {2, 4, 5, 1, 1, 6, 14, 8, 2, 12, 1, 13, 10, 2, 8, 5, 9, 1};
size_t n = (sizeof a) / (sizeof *a);
// Expected: 10, because of 1 1 1 1 2 2 2 4 8 8
printf("%d\n", count_dividends(n, a));
}
{
int a[] = {2, 4, 5, 2, 7, 10, 9, 8, 2, 4, 4, 6, 5, 8, 4, 7, 6};
size_t n = (sizeof a) / (sizeof *a);
// Expected: 9, because of 2 2 2 4 4 4 4 8 8
printf("%d\n", count_dividends(n, a));
}
}
I am writing a program to break numbers in an array into their digits then store those digits in a new array. I have two problems:
It does not display the first number in the array (2) when transferred to the second array, and I am not entirely sure why.
The array may contain 0's, which would break my current for loop. Is there another way to implement a for loop to only run for as many numbers are stored in a array without knowing how big the array is?
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
// Setting an array equal to test variables
int sum[50] = { 2, 6, 3, 10, 32, 64 };
int i, l, k = 0, sumdig[10], dig = 0;
// Runs for every digit in array sum, increases size of separate variable k every time loop runs
for (i = 0; sum[i] > 0; i++ && k++)
{
sumdig[k] = sum[i] % 10;
dig++;
sum[i] /= 10;
// If statement checks to see if the number was two digits
if (sum[i] > 0)
{
// Advancing a place in the array
k++;
// Setting the new array position equal to the
sumdig[k] = sum[i] % 10;
dig++;
}
}
// For testing purposes - looking to see what digits have been stored
for (l = 0; l < dig; l++)
{
printf("%i\n", sumdig[l]);
}
}
This is the output:
6
3
0
1
2
3
4
6
0
Solution:
It does not display the first number in the array (2) when transferred to the second array
changes i++ && k++ into i++,k++
Is there another way to implement a for loop to only run for as many numbers are stored in an array
There are many different ways but here is some to illustrate it in a few different scenarios:
1. The array length is known and fixed:
Let the compiler automatically allocate the array for you. And then for(i=0; i<6; i++)
2. Able to calc the array length:
Then count the number of elements when initializing the array into a varible. Then just for(i=0; i<SizeCount; i++)
3. Not-able to know array size for some reason:
It is rare but, in that case, you can pre-set a stop criteria i.e. -1 or some other flag so that you can stop when it reaches the terminator i.e. set or pre-set all other values of sum to be -1. Then you can while(sum[i] != -1) This is how string lengths work in C, either with NULL termination (string end with the number 0 or value NULL) or, with input, the line break character \n indicating a termination.
DEMO
Here is a demo of full code with some explanation:
#include <stdio.h>
int main(void){
int sum[] = {2, 6, 3, 10, 32, 64}; // compiler is smart enough know the size
int i, k = 0, sumdig[10], dig = 0;
// Runs for every digit in array sum, increases size of seperate variable k everytime loop runs
for(i = 0; i < sizeof(sum)/sizeof(int); i++, k++){
sumdig[k] = sum[i] % 10;
dig++;
sum[i] /= 10;
// If statement checks to see if the number was two digits
if (sum[i] > 0)
{
// Advancing a place in the array
k++;
// Setting the new array position equal to the
sumdig[k] = sum[i] % 10;
dig++;
}
}
// For testing purposes - looking to see what digits have been stored
for(i = 0; i < dig; i++){
printf("%i\n", sumdig[i]);
}
}
Compile and run
gcc -Wall demo.c -o demo
./demo
Output
2
6
3
0
1
2
3
4
6
I input 4566371 and find out that uninitialized array elements are not 0 as said in our texts
#include <stdio.h>
#define MAX 10
// Function to print the digit of
// number N
void printDigit(long long int N)
{
// To store the digit
// of the number N
int array_unsorted[MAX];//array_unsorteday for storing the digits
int i = 0;//initializing the loop for the first element of array_unsorted[]
int j, r;
// Till N becomes 0,we will MOD the Number N
while (N != 0) {
// Extract the right-most digit of N
r = N % 10;
// Put the digit in array_unsorted's i th element
array_unsorted[i] = r;
i++;
// Update N to N/10 to extract
// next last digit
N = N / 10;
}
// Print the digit of N by traversing
// array_unsorted[] reverse
for (j =MAX; j >=0; j--)
{
printf("%d ", array_unsorted[j]);
}
}
// Driver Code
int main()
{
long long int N;
printf("Enter your number:");
scanf("%lld",&N);
printDigit(N);
return 0;
}
output:
Enter your number:4566371
77 0 8 32765 4 5 6 6 3 7 1
Process returned 0 (0x0) execution time : 2.406 s
Press any key to continue.
The other values should be o right?Why 77,0,32765 this way?Why not all are 0?like 0 0 0 0 4 5 6 6 3 7 1?
An array of integers declared inside a function has indeterminate values if it is uninitialized. If a similar array is declared at global scope, outside all functions, it will be initialized with zeros by default.
To make an array that is always initialized to zeros, do this:
int array_unsorted[MAX] = {0};
This works because in C, = {0} will initialize all values with zero. If you say = {10, 20} it will initialize the first two elements as written, and the rest to zero.
You have correctly reserved a memory space for your array array_unsorted but the memory has not been cleaned before use. This memory reserved it was probably used by another function or variable before yours! This is why it already has some values in it. You should set it to 0 manually before starting to use it.
As noted in other answers, you may want to initialize your integer array. Whether or not you do that, you might want to replace the for loop statement conditions of:
for (j =MAX; j >=0; j--)
with:
for (j = i - 1; j >=0; j--) /* Start at the place the digit storage ended */
That way, you are not moving into array elements that were not used in the digit storage portion of your function.
Regards.
I'm trying to solve a question to find the lowest and highest numbers in an array in C Language. I tried swapping the numbers that are close to each other to align the numbers from small(left) to big(right).
For example, if the array is 20, 10, 35, 30, 7, first compare 20 and 10, if 20 is larger than 10, swap the numbers to 10, 20. then compare 20 and 35, 20 is smaller than 35, so go on. then compare 35 and 30, 35 is bigger than 30, swap numbers to 30, 35. then compare 35 and 7, 35 is bigger than 7, swap numbers to 7, 35.
Did these 'swappings' again 3 more times to align the numbers perfectly.
After I've done the swappings, I just printed the first array number and the last array number, but the numbers aren't correct, and it looks like the numbers have shifted by 1. For example, if I align the above array, it is 7[0], 10[1], 20[2], 30[3], 35[4]. (marked the indices by []) So, when I print the indice[0], and indice[4], I expected the numbers to show 7 and 35.
But in fact I have to print indice[1], and indice[5] to get the numbers 7 and 35 to be printed. The numbers seem to have shifted by 1..
I really want to know why the numbers have shifted by 1 in the array.
Thank you for reviewing the question.
I'll also post the original question that I'm trying to solve.
"Q. Input the number N first to decide how much numbers to enter, then input the N-numbers. Print the lowest and highest number in the N-numbers you have input."
And here's my code:
#include<stdio.h>
#pragma warning(disable:4996)
int main(void)
{
int input, i, j, temp, k;
int value[100] = { 0 };
scanf("%d", &input);
for (i = 0; i < input; i++)
{
scanf("%d", &value[i]);
}
for (k = 0; k < input; k++)
{
for (j = 0; j < input; j++)
{
if (value[j] > value[j + 1])
{
temp = value[j + 1];
value[j + 1] = value[j];
value[j] = temp;
}
}
}
printf("%d %d\n", value[0], value[input-1]);
return 0;
}
Because you're iterating over the whole array, value[j+1] walks off the end of the user's input. Since value was initialized 0 to, temp = value[j + 1] will be 0. So 0 will always be your min (unless the user enters negatives).
Instead, iterate only up to j < input - 1.
I'm trying to solve a question to find the lowest and highest numbers in an array in C Language.
You don't need to sort the array, you can do this in a single pass.
// Initialize min and max to be the first value.
int min = value[0];
int max = value[0];
// Then loop through the rest of the array checking if each value is
// smaller than min and/or larger than max.
for (i = 1; i < input; i++) {
if( value[i] < min ) {
min = value[i];
}
if( value[i] > max ) {
max = value[i];
}
}
printf("min: %d, max: %d\n", min, max);
Note: It's not necessary to declare all your variables up front. You can declare them as you need them. And you don't need different iterators for each loop, you can reuse i as I have above.
I'm kind of new in C programming and I'm trying to make a program that prints the nth term of a series and every 5 counts, it adds up by 5.
Example: 1, 2, 3, 4, 9, 10, 11, 12, 17, 18, 19, 20, 25......
Here is my code
int num,digit,count = 1;
printf("Enter n: ");
scanf("%d", &num);
for(int i=1; i<=num; i++){
count++;
if(count > 5){
count = 0;
i+=4;
}
printf("%d ",i);
}
My code doesn't get to the specific nth term that I'm asking for. For example, I've inputted 10 and it only shows up until the 6th term
The thing to do is get clear in your head what you want to do and how you are going to do it. Rather than tinkering with code, break things down into simple parts and make them clear.
#include <stdio.h>
int main(void)
{
int num = 10;
// Method 1: Spell everything out.
// i counts number of terms printed.
// j counts number of terms since last multiple of four terms.
// k is current term.
for (
int i = 0, j = 0, k = 1; // Initialize all counters.
i < num; // Continue until num terms are printed.
++i) // Update count.
{
printf("%d ", k); // Print current term.
++j; // Increment four-beat count.
if (4 <= j)
{
// Every fourth term, reset j and increment the term by 5.
j = 0;
k += 5;
}
else
// Otherwise, increment the term by 1.
k += 1;
}
printf("\n");
// Method 2: Use one counter and calculate term.
// Iterate i to print num terms.
for (int i = 0; i < num; ++i)
/* Break the loop count into two parts: the number of groups of 4
(i/4) and a subcount within each group (i%4). Looking at the
starts of each group (1, 9, 17, 25...), we see each is eight
greater than the previous one. So we multiply the group number by
8 to get the right offsets for them. Within each group, the term
increments by 1, so we use i%4 directly (effectively multiplied by
1). Then (i/4)*8 + i%4 would start us at 0 for i=0, but we want to
start at 1, so we add 1.
*/
printf("%d ", (i/4)*8 + i%4 + 1);
printf("\n");
}
You shall not change the variable i within the body of the for loop.
You need to introduce one more variable that will store the current outputted number.
Here is a demonstration program.
#include <stdio.h>
int main(void)
{
unsigned int n = 0;
printf( "Enter n: " );
scanf( "%u", &n );
for ( unsigned int i = 0, value = 0, count = 1; i < n; i++ )
{
if ( count == 5 )
{
value += 5;
count = 1;
}
else
{
++value;
}
printf( "%u ", value );
++count;
}
}
The program output is
Enter n: 13
1 2 3 4 9 10 11 12 17 18 19 20 25
Here's another take that I think is a bit less complicated, with explanations in the comments:
#include <stdio.h>
int main(void)
{
int num, count = 1;
num = 20;
// if you look closely, you actually have an initial condition before the
// main pattern starts. Once the pattern starts, its actually every _fourth_
// term that gets added by 5. You'll make things easier on yourself if you
// print out this initial condition, then handle the pattern in the loop.
// If you really want to be correct, you can wrap this in a if (num > 0) check
printf("%d ", count++);
// start at 1, because we already printed the first item
for(int i=1; i<num; i++, count++)
{
// now we can focus on every fourth term
if (i % 4 == 0)
{
// if it's the fourth one, add 5 to the previous value
// Of course this simplifies to count += 4
count = (count-1) + 5;
}
printf("%d ",count);
}
}
Demonstration