问题
i've been stuck for hours trying to figure how can i write a function that gets and array of integers, and finds the length of the longest ascending sub-series in the array using recursion and no loops at all. im only allowed to use another 1 recursive function for example, for the following array: {45,1,21,3,3,6,53,9,18} the outpot should be 5, because the longest sub-series is {1,3,6,9,18}. So, basicly, a function that gets an array and its size, and needs to print the length of the longest sub-series using no loops at all, no global/static types, and it may use another "help" recursive function and thats it. this is pretty much all i came up with, and its a mess and not working well. I'm trying to scan the array while at all time i know the current index im looking at, the index that is being compared to the current, and the originla index from which i started the current sub-series. I tried to scan the array while knowing the indexes that should be compared but i got stuck, here's what i got, i would really appreciate any tips and advices. thanks.
void max_set(int arr[], int size)
{
int bigSeries[2] = { 0 };
calcSeries(arr, bigSeries,0, 0, 1, size -1, 1);
printf("number of max parts going up %d \n", bigSeries[0]);
}
void calcSeries(int arr[], int bigSeries[],int originalCHeckedIndex, int checkedIndex, int currentIndex, int lastIndex, int ascending)
{
if ((checkedIndex == lastIndex) || (currentIndex > lastIndex))
{
if (ascending > bigSeries[0])
bigSeries[0] = ascending;
if (originalCHeckedIndex == lastIndex)
return;
else
{
calcSeries(arr, bigSeries, originalCHeckedIndex + 1, originalCHeckedIndex + 1, originalCHeckedIndex + 2, lastIndex, 0);
return;
}
}
if (arr[currentIndex] > arr[checkedIndex])
{
calcSeries(arr, bigSeries, originalCHeckedIndex, currentIndex, currentIndex + 1, lastIndex, ascending + 1);
}
else
{
if (arr[originalCHeckedIndex] < arr[currentIndex])
calcSeries(arr, bigSeries, currentIndex, currentIndex, currentIndex + 1, lastIndex,ascending);
calcSeries(arr, bigSeries, originalCHeckedIndex, checkedIndex, currentIndex + 1, lastIndex, ascending);
}
}
回答1:
The algorithm has many similarities with the one of first answer, yet covering a few corner cases you might want to watch out. Instead of writing a lengthy comment, I chose to write a new answer instead.
Sanity Checks
Do some sanity checks on the array, as I did in function max_set().
- Is an array supplied at all (check for NULL)?
- Is the supplied array size at least positive (consider size_t)?
Allowed Values
Data type int allows positive and negative values. The algorithm should handle both. At least I didn't read from your post that they have to be positive. My code looks a bit nicer if you skip that part.
Recursion
The idea of this algorithm (and the one from first answer) is to recursively walk through the array, beginning at the first element, ending at last. So this already defines the start and end of recursion, as documented in source code.
To find the longest sub-series of numbers this way, there are always three possibilities:
- The longest sub-series can be reached by skipping the number that is currently processed
- The longest sub-series can be reached by adding the number that is currently processed
- The currently processed number cannot fit in
A number can be added if it's larger than the largest previously added number; we look for an ascending series after all. The current number could be larger than others in the array that have to be processed, yet. So we have to take both possibilities into account: continuing recursive steps without it and with it -- as long as it fits criteria.
Possible oversight
Take into account that INT_MIN, the smallest possible int value on the machine, is a perfectly valid number in the array. I have added the variable seen, which just records if INT_MIN has been seen at least once in the array or not. On first encounter, seen flips from 0 to 1, not allowing any further INT_MIN values due to requirement of ascending sub-series. Your example shows this requirement with two occurences of number 3.
Tests
Try to find various test cases, and think out of the box at times. NULL for array, negative size, empty array. Next, add fancy values like negative numbers, INT_MIN. Or create ascending series, descending ones, interlacing. Numbers occuring multiple times ...
#include <sys/limits.h>
#include <stdio.h>
int
analyze(int arr[], int size, int min, int seen)
{
int sub_count = 0, count = 0;
/* end of recursion */
if (size == 0)
return 0;
/* recursion step, without and with current number */
sub_count = analyze(arr + 1, size - 1, min, seen);
if (arr[0] > min || (min == INT_MIN && arr[0] == INT_MIN && !seen))
count = 1 + analyze(arr + 1, size - 1, arr[0], arr[0] == INT_MIN);
/* return length of largest sub-series */
return sub_count > count ? sub_count : count;
}
void
max_set(int arr[], int size)
{
int seq = 0;
if (arr != NULL && size > 0) {
/* start of recursion */
seq = analyze(arr, size, INT_MIN, 0);
}
printf("max sequence is %d\n", seq);
}
int
main(void)
{
int arr[] = { 45, 1, 21, 3, 3, 6, 53, 9, 18 };
max_set(arr, sizeof(arr) / sizeof(*arr));
return (0);
}
回答2:
#include <stdio.h>
int calcSeries(int arr[], int size, int value, int count){
int self, skip, rest;
if(0 == size)
return count;
skip = calcSeries(arr + 1, size-1, value, count);//case of skip the top(self)
if(value < *arr){
self = calcSeries(arr + 1, size-1, *arr, count+1);//case of include top
if(skip > self)
self = skip;
} else
self = skip;
rest = calcSeries(arr + 1, size-1, -1, 0);
return self > rest ? self : rest;
}
void max_set(int arr[], int size){
printf("number of max parts going up %d \n", calcSeries(arr, size, -1, 0));
}
int main(void){
int array[]={45,1,21,3,3,6,53,9,18};
max_set(array, sizeof(array)/sizeof(*array));
return 0;
}
来源:https://stackoverflow.com/questions/20314420/finding-the-length-of-the-longest-ascending-sub-series-in-an-array-using-recursi