Can we modify this nested loop to recursive function?
Target: Find two indice in an int array whose sum equal to given target value. Here's the working iterative code, how can I consider this function in a different way as a recursive?
#include<stdio.h>
#define SIZE 15
int find_indice(const int arr[],int size,int target,int *ind_1,int *ind_2);
int main(){
int arr[SIZE]={0,1,3,4,5,6,7,8,9,15,-5,0,9,10,23};
int target=-2;
int ind1,ind2;
find_indice(arr,SIZE,target,&ind1,&ind2);
if(ind1!=-1 && ind2!=-1){
printf("array[%d]=>%d,array[%d]=>%d \n",ind2,arr[ind2],ind1,arr[ind1]);
}
else{
printf("Not found! \n");
printf("array[%d]=>%d,array[%d]=>%d \n",ind2,0,ind1,0);
}
return 0;
}
int find_indice(const int arr[],int size,int target,int *ind_1,int *ind_2){
int i,j,found=0;
for(i=0;i<size-1;i++){
for(j=0;j<size;j++){
if((arr[i]+arr[j])==target){
*ind_1=i;
*ind_2=j;
found=1;
}
}
}
if(found==0){
*ind_1=-1;
*ind_2=-1;
}
return 0;
}
I don't know how to turn your loops into a recursive call of the same function, but here are a few remarks on your code:
the printf statement is meaningless in case you do not find the indices.
Why do you stop at i<size-1 in the outer loop? The test should be i < size, unless you want indices to be different, but your code does not implement this constraint.
find_indice() should return the found status, it would be much simpler than storing bogus indices in *ind_1 and *ind_2, and would allow you to use the proper type for array indices: size_t.
You should return from find_indice() immediately when you find a match, no need to try all possibilities.
You can halve the running time by starting the inner loop at j=i instead of j=0. Note that for a different target, say -10, find_indice() could return the same index in both *ind_1 and *ind_2. This may not be what is expected. You would start the inner loop at j=i+1 if it is not wanted.
Related
I was making this binary search function in c, but have encountered a problem. I have passed a pointer of a sorted array, its (size-1) and the number to be searched. When I try to compare values at the front position and last position in the while loop, its not working for the values on the right of middle element. For eg, if I pass a array={1,2,3,4,5} for {1,2,3}, the function works fine, however for {4,5} the loop just runs once and exits.
There's one more issue, this problem only happens if we compare the values on the address of the pointers, but if I compare the pointers instead, the function works perfectly. Better explained in the code given below.
int binarysearch(int*p,int r,int num){
//p is pointer of an array, r is the (sizeof(array)-1), num is the number to be searched
int *mid;
while(*p<=*(p+r)){//if we replace the condition with(p<=(p+r)) the function works
mid=(p+(r/2));
printf("1 ");
if(*mid==num)
return *mid;
if(*mid<num)
p=mid+1;
else
r=((r/2)-1);
}
return -1;
}
Check out the way you calculate the mid value.
In the first iteration, mid=(p+(r/2)) will give you the middle term correctly. Let say r=5, and that in the first iteration we got *mid<num so now p=mid+1 or p=p+3.
The problem now is that r is still 5 so the array pointer just got shifted away from its values without marking the new end. This can easily lead to segmentation fault if you will try to use your result address later.
the solution is simple: don't calculate the mid position with a pointer and int. Use two pointers to mark the search bounders or two integers to mark their indexes.
You can also use your way, but be sure to update r size every iteration.
First option - using indexes (my choice if I had to make one):
int binarysearch(int*p,int r,int num){
int mid;
int a=0;
while(a<=r) {
mid=(a+r)/2;
printf("1 ");
if(p[mid]==num)
return *mid;
else if(p[mid]<num)
a=mid+1;
else if(a==r)
break;
else
r=mid;
}
return -1;
}
Second option - your fixed version:
int binarysearch(int*p,int r,int num){
int *mid;
while(r>=0) {
mid=p+(r/2);
printf("1 ");
if(*mid==num)
return *mid;
else if(*mid<num) {
p=mid+1;
r-=(r/2)+1;
}
else if (r==0)
break;
else
r/=2;
}
return -1;
}
I am looking for help regarding the implementation of a counting sort function in the CS50 Course in week 3.
An int Array has to be sorted.
I tested various unsorted arrays and my counting sort function seems to sort the array just correctly, yet my search functions won't work on the sorted array after.
Could someone give me a hint?
void countsort( int array[], int size) {
int count=0;
int zahl=0;
int max=65536;
int countarr [max];
int finalarr [size];
memset (countarr, 0, sizeof(countarr));
for(int i=0;i<size;i++) {
zahl=array[i];
countarr[zahl]++;
}
for(int i=0;i<max;i++) {
while(countarr[i]>0) {
finalarr[count]=i;
countarr[i]--;
count++;
}
}
array=finalarr;
for(int i=0;i<size;i++){
printf(" %i ",array[i]);
}
}
This is my search algorithm used after the array is sorted, it works with sort algorithms from other people.
bool binarysearch(int value, int values[], int n){
int start=0,
end=n,
mid=0,
midpos=0;
while(end>0) {
midpos=(start+end)/2;
mid=values[midpos];
if(mid==value) return true;
if(mid<value) start=++midpos;
if(mid>value) end=--midpos;
}
return false;
}
In binarysearch, the loop condition while(end>0) is wrong.
If we search for a value which is greater than at least one of the elements of the array, end will never be zero.
Try changing it to while(end>=start), which literally means that the considered interval is non-empty.
In countsort, the line array=finalarr; does not copy the whole array.
Instead, the local variable array becomes a pointer to finalarr.
The contents of the original array remain unchanged, and the sorted array is gone when you exit the function.
This explains why your binary search works (better) with other sort functions.
Try changing finalarr[count]=i; to array[count]=i; and get rid of finalarr completely, putting the values into array right away.
Alternatively, you can use memmove instead of that line.
I have two arrays, namely a[] and b[]. I would like to search if any element of a is present in b. Note that I do not want to find all duplicate occurrences, if any one element from a[] exists in b[], I would like to report it and break out without checking the rest of a[] or b[]
I'm a bit confused about how 'break' operates. Can 'break' break out of any kind of loop - for/while, but it breaks out of only the 'innermost loop' around where it's placed in code ?
This is my solution and please suggest if there is a better implementation for this O(n^2) approach
#include <stdio.h>
int main(void)
{
int a[] = {1,2,3,4,5,6};
int b[] = {11,2,3,7,8,9,6,10,11};
int i = 0, j = 0;
int duplicate = 0;
for(i=0;i<sizeof(a)/sizeof(int);i++)
{
for(j=0;j<sizeof(b)/sizeof(int);j++)
{
if(a[i] == b[j])
{
printf("Duplicates found for [%d]\n",a[i]);
duplicate = 1;
break;
}
}
if(duplicate == 1)
{
break;
}
}
return 0;
}
break only breaks the innermost loop in which it is used. If you want to avoid the ugly syntax then you have multiple solutions:
ignore this optimization until you prove it's relevant
move the code inside a function that accepts the two arrays as arguments so that you can directly return from the function without having to break.
adjust indices i and j after that you found a duplicate to make both loops return gracefully
use a goto instruction (which is not advisable in any case)
Other solutions, with complexity lower than O(n^2) could require some additional data structure, like a hashset or sorting of data.
breaks generally break out of the most inner loop in c. You have used it correctly.
if u want to just report a duplicate, then u can put this code into a fuction and whenever a duplicate is found, you just return. The function would look like this:
//Here a and b are pointers to array
//n1 and n2 are number of elements in array a,b
chk_dup(int *a,int *b,int n1,,int n2){
for(i=0;i<n1;i++)
{
for(j=0;j<n2;j++)
{
if(a[i] == b[j])
{
printf("Duplicates found for [%d]\n",a[i]);
//duplicate = 1;
//break;
return;
}
}
}
}
You cannot use sizeof(a) here becoz its just a pointer to array.Same goes for sizeof(b).
You can make this algorithm more efficient by sorting the arrays using quicksort(that would take O(nlgn)) and then for each element in a do binary search in b.
pseudo code for that is something like this:
//Here a and b are pointers to sorted arrays
//n1 and n2 are number of elements in array a,b
chk_dup(int *a,int *b,int n1,,int n2){
for(i=0;i<n1;i++)
{
//find a[i] in b using binary search.
int found=binary_search(a[i],b);
if(found){
printf("Found Duplicate");
return;
}
}
printf("No duplicate found");
}
So, the whole algorithm works in O(nlgn). While the algorithm you are using can take O(n^2).
Otherwise your code is perfectly fine and the use of break is correct
You could use goto as noted here How to break out of nested loops? it's the last remaining valid use of this...
And maybe there is a better solution using xor, not sure if you can reduce the
complexity though...
I write a program to sum the elements in an array. However, when I am compiling the program, it tells me that "control may reach end of a non void function". I don't know why.
//a program to sum the elements of an array
#include <stdio.h>
int sum(int array[],int n)
{
int sum =0, *ptr;
int *arrayend=array +n;
for(ptr=array; ptr<arrayend;++array)
{
sum +=*ptr;
return sum;
}
}
int main(void)
{
int sum(int array[],int n);
int value[10]={1,2,3,4,5,6,7,8,9,10};
printf("The sum is %i\n",sum(value,10));
return 0;
}
Your function sum() is poorly formed and let's say the for loop condition fails at first attempt and you never enter the loop then you have a situation where you are not returning anything and your function return type is int
So this case needs to be addressed so that even if you fail to enter the loop there should be return after the loop.
return within a loop makes no sense unless there is a condition based on which you return.
You try to return sum each time the loop body is executed, but functions only return once. So on the first iteration of the loop the function will return. That's the same as having no loop.
You need to put return sum after the loop, so that your loop makes sense. I.e. first add *ptr to sum n times, then return the resulting sum.
Also, in the loop you do ++array. That should probably be ++ptr.
I am writing a program which have to generate N random not repeating numbers
the prototype should be voidrandom_int(int array[], int N);
it is not having any errors but it is not working. Not even giving any number
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void random_init(int array[], int N)
{
srand(time(NULL));
int i, j;
array[0]=rand()%N;
for(i=1;i<N;i++)
{
array[i]=rand()%N;
if(array[i]==0)
array[i]=1;
for(j=0;j<i;j++)
{
if(array[i]==array[j])
break;
}
if((i-j)==1)
continue;
else
i--;
}
}
int main(void)
{
int a[5], i, N;
N=5;
random_init(a,N);
for(i=0;i<N;i++)
printf("%d ", a[i]);
return 0;
}
This part makes no sense:
if(array[i]==0)
array[i]=1;
It will limit your choices to N-1 numbers (1 to N-1), out of which you try to find N numbers without repetition - leading to an infinite loop.
if((i-j)==1)
continue;
Here you probably want if (i==j) instead, to check if the previous loop ran to completion.
A faster and simpler way to generate the numbers 0..N-1 in a random order, is to put these numbers in an array (in sequential order), and then use Fisher-Yates Shuffle to shuffle the array.
This method is biased. Do not use it other than for educational purposes.
Other than Ficher-Yates, which uses another array, you can use the method of going through all the available numbers and find a "random" spot for them (effectively "initializing" the array twice). If the spot is taken, choose the next one. Something like this, in pseudo-code:
fill array with N
for all numbers from 0 to N-1
find a random spot
while spot is taken (value is N) consider next spot /* mind wrapping */
set value in current spot