Skip to content

Commit c31eb74

Browse files
committed
new question added
1 parent a3202f8 commit c31eb74

File tree

7 files changed

+354
-2
lines changed

7 files changed

+354
-2
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ is known.
167167
- For problems involving subsequences, we can break them down to smaller problems. Specifically for
168168
linear array, array of length 1 less than total can be taken and a pattern can be found for dynamic programming to make recursive equations.
169169
- Sometimes results of two DP solutions can be merged using some algo to find the final result.
170+
- To breakdown any question to DP (recursive equation), follow the crux of the question and break
171+
it down into a story and later generalize to form recursive equations
170172

171173
# Topic0: Programming Questions
172174

@@ -379,7 +381,10 @@ linear array, array of length 1 less than total can be taken and a pattern can b
379381
- [Find the longest decreasing subsequence](/dynamic-programming/question14.c)
380382
- [Perfect hill longest subsequence](/dynamic-programming/question15.c)
381383
- [Given two words, word1 and word2, find min operations to convert word1 to word2 with some given set of rules](/dynamic-programming/question16.c)
382-
384+
- [Largest sum independent set in a binary tree](/dynamic-programming/question17.c)
385+
- [Find the number of n-bit integers which do not have any two consequent zeroes](/dynamic-programming/question18.c)
386+
- [Given a sentence without spaces between words. Break the words in such a way that they are meaningful](/dynamic-programming/question19.c)
387+
- [Partition problem](/dynamic-programming/question20.c)
383388

384389
## Some important concepts to solve algos better
385390

dynamic-programming/a.exe

-446 Bytes
Binary file not shown.

dynamic-programming/question17.c

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
Largest sum independent set in a binary tree
3+
4+
Independent set means no two nodes are adjacent to each other. Eg:
5+
6+
10
7+
5 6
8+
4 3 7 8
9+
9 12 13 14 15 16 19 21
10+
In the above tree if I choose 10, I cannot choose 5 and 6 as they are adjacent to 10.
11+
If I choose 5, I cannot choose 10, 4 and 3 and so on.
12+
13+
METHOD:
14+
Naive approach: Here there are two cases for every tree or subtree present (either to include the node
15+
or to not include it)
16+
17+
Therefore LIS(root) = max {
18+
cost(root) + cost of all its grandchildren,
19+
cost of all its children of root
20+
}
21+
22+
Therefore for each node the number of possibilities increase as we go down the tree. Hence,
23+
exponential time complexity.
24+
25+
*/
26+
//naive approach implementation
27+
#include <stdio.h>
28+
#include <stdlib.h>
29+
30+
struct node{
31+
int data;
32+
struct node *left;
33+
struct node *right;
34+
};
35+
36+
struct node *newNode(int data){
37+
struct node *temp = (struct node *)malloc(sizeof(struct node));
38+
temp->data = data;
39+
temp->left = temp->right = NULL;
40+
return temp;
41+
}
42+
43+
int findMax(int a,int b){
44+
return (a>b)?a:b;
45+
}
46+
47+
int LISS(struct node *root){
48+
if(!root){
49+
return 0;
50+
}
51+
//size excluding the current node
52+
int size_excl = LISS(root->left) + LISS(root->right);
53+
//size including
54+
int size_incl = 1;
55+
if (root->left)
56+
size_incl += LISS(root->left->left) + LISS(root->left->right);
57+
if (root->right)
58+
size_incl += LISS(root->right->left) + LISS(root->right->right);
59+
return findMax(size_excl, size_incl);
60+
}
61+
62+
int main(){
63+
struct node *root = newNode(20);
64+
root->left = newNode(8);
65+
root->left->left = newNode(4);
66+
root->left->right = newNode(12);
67+
root->left->right->left = newNode(10);
68+
root->left->right->right = newNode(14);
69+
root->right = newNode(22);
70+
root->right->right = newNode(25);
71+
72+
int size = LISS(root);
73+
printf("size of independent set with max sum is %d\n", size);
74+
return 0;
75+
}
76+
77+
78+
//dynamic programming approach
79+
#include <stdio.h>
80+
#include <stdlib.h>
81+
82+
struct node{
83+
int data;
84+
int liss;
85+
struct node *left;
86+
struct node *right;
87+
};
88+
89+
struct node *newNode(int data){
90+
struct node *temp = (struct node *)malloc(sizeof(struct node));
91+
temp->data = data;
92+
temp->liss = 0;
93+
temp->left = temp->right = NULL;
94+
return temp;
95+
}
96+
97+
int findMax(int a,int b){
98+
return (a>b)?a:b;
99+
}
100+
101+
int LISS(struct node *root){
102+
if(!root){
103+
return 0;
104+
}
105+
if(root->liss){
106+
return root->liss;
107+
}
108+
109+
if(!root->left && !root->right){
110+
return (root->liss = 1);
111+
}
112+
//size excluding the current node
113+
int size_excl = LISS(root->left) + LISS(root->right);
114+
//size including
115+
int size_incl = 1;
116+
if (root->left)
117+
size_incl += LISS(root->left->left) + LISS(root->left->right);
118+
if (root->right)
119+
size_incl += LISS(root->right->left) + LISS(root->right->right);
120+
return findMax(size_excl, size_incl);
121+
}
122+
123+
int main(){
124+
struct node *root = newNode(20);
125+
root->left = newNode(8);
126+
root->left->left = newNode(4);
127+
root->left->right = newNode(12);
128+
root->left->right->left = newNode(10);
129+
root->left->right->right = newNode(14);
130+
root->right = newNode(22);
131+
root->right->right = newNode(25);
132+
133+
int size = LISS(root);
134+
printf("size of independent set with max sum is %d\n", size);
135+
return 0;
136+
}

dynamic-programming/question18.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
Find the number of n-bit integers which do not have any two consequent zeroes
3+
4+
Here it means that if there a number n which is represented by bits
5+
10101.. it should not contain any two consecutive zeroes.
6+
7+
Since a number is represented as 0 or 1, there are in total 2^n ways to rearrange them for n bit
8+
integer. To validate if any 0s are occuring together will take another O(n) time.
9+
Therefore time complexity in this case is exponential.
10+
11+
METHOD:
12+
DP:
13+
Here if we have an n bit integer, it can either start from 1 or 0,
14+
it it starts from 1 next number can be 1 also and 0 also, hence problem is broken into n-1
15+
parts
16+
but if it starts from 0 the next number has to be 1, it cannot be zero. Hence here problem
17+
now is n-2 size.
18+
Therefore
19+
f(n) = f(n-1) + f(n-2)
20+
21+
This is nothing but the program to fibonacci series where memoization can be used
22+
23+
Time complexity: O(n)
24+
Space complexity: O(n)
25+
*/
26+
27+
#include <stdio.h>
28+
#include <stdlib.h>
29+
30+
int fib(int n){
31+
int f[n+1];
32+
int i;
33+
f[0] = 0;
34+
f[1] = 1;
35+
for(i=2;i<=n;i++){
36+
f[i] = f[i-1] + f[i-2];
37+
}
38+
return f[n];
39+
}
40+
41+
int main(){
42+
int n = 9;
43+
printf("total here is: %d\n", fib(n));
44+
return 0;
45+
}
46+
47+
48+
//RECURSIVE
49+
#include <stdio.h>
50+
#include <stdlib.h>
51+
#define MAX 100
52+
53+
int f[MAX];
54+
55+
int fibRecursive(int n){
56+
if(f[n] == -1){ //if does not exist then only compute
57+
if(n < 2){
58+
f[n] = n;
59+
}
60+
else{
61+
f[n] = fibRecursive(n-1) + fibRecursive(n-2);
62+
}
63+
}
64+
return f[n];
65+
}
66+
67+
void initialize(int n){
68+
int i;
69+
for(i=0; i<=n;i++){
70+
f[i] = -1;
71+
}
72+
}
73+
74+
int main(){
75+
int n = 9;
76+
initialize(n);
77+
printf("total here is: %d\n", fibRecursive(n));
78+
return 0;
79+
}

dynamic-programming/question19.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
Given a sentence without spaces between words. Break the words in such a
3+
way that they are meaningful
4+
5+
How to test if words are meaningful or not:
6+
Assume that there is already a hash data structure with all the meaningful words present in it.
7+
8+
NAIVE approach: In worst case if we try to break the word after each character, total characters
9+
being n, n-1 spaces can be inserted. Therefore after each character either a space can be inserted
10+
or either it cannot be inserted.
11+
Hence 2^n-1 ways are there and total n words can be formed and to check each word O(1) time is required.
12+
Total time complexity is exponential
13+
14+
METHOD:
15+
Dynamic programming:
16+
17+
*/

dynamic-programming/question20.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
Partition problem
3+
4+
Here we need to divide the array into two parts where the difference in the sum of the two parts
5+
is minimum.
6+
7+
If we go by naive approach, we can either include an element or exclude it, like this total combinations
8+
will be 2^n, which needs to be scanned Therefore time complexity is exponential
9+
10+
METHOD
11+
DP: Here for two parts to have equal sum, the net sum of the array needs to be even. Therefore we first
12+
check that.
13+
When its even, we divide it by two and apply the subset sum method. Finding a subset in the array
14+
whose sum is equal to a given value.
15+
16+
Therefore we use a 2d array in that case where columns indicate sum value from 1 to given value.
17+
Rows indicate the values in the array
18+
Each cell means, whether considering elements uptil that row, the column value is possible or not.
19+
Therefore we get the final answer.
20+
21+
Time complexity: O(nk)
22+
Space complexity: O(nk) //where k is the value of the sum.
23+
24+
This method cannnot be applied for large values of k
25+
26+
*/
27+
//Naive approach
28+
// #include <stdio.h>
29+
// #include <stdlib.h>
30+
31+
// int isSubsetSum(int *arr, int size, int sum){
32+
// if(!sum)
33+
// return 1;
34+
// if(!size && sum)
35+
// return 0;
36+
// if(arr[size-1]>sum)
37+
// return isSubsetSum(arr,size-1,sum);
38+
39+
// return isSubsetSum(arr,size-1,sum) || isSubsetSum(arr,size-1,sum-arr[size-1]);
40+
// }
41+
42+
// int findPartition(int *arr,int size){
43+
// int sum = 0;
44+
// int i;
45+
// for(i=0;i<size;i++){
46+
// sum += arr[i];
47+
// }
48+
// if(sum%2 !=0) return 0;
49+
50+
// return isSubsetSum(arr,size,sum/2);
51+
// }
52+
53+
// int main(){
54+
// int arr[] = {3,1,5,9,12};
55+
// int size = sizeof(arr)/sizeof(arr[0]);
56+
// if(findPartition(arr,size)){
57+
// printf("can be divided\n");
58+
// }else{
59+
// printf("cannot be divided\n");
60+
// }
61+
// return 0;
62+
// }
63+
64+
//Better method
65+
#include <stdio.h>
66+
#include <stdlib.h>
67+
68+
int findPartition(int *arr, int size){
69+
int sum = 0;
70+
int i, j;
71+
for(i=0; i<size; i++){
72+
sum += arr[i];
73+
}
74+
75+
if(sum%2 !=0){
76+
return 0;
77+
}
78+
79+
int part[sum/2+1][size];
80+
81+
for(i=0;i<size;i++){
82+
part[i][0] = 1;
83+
}
84+
85+
for(i=0;i<size;i++){
86+
for(j=1;j<=sum/2;j++){
87+
part[i][j] = part[i-1][j] || part[i-1][j-arr[i]];
88+
}
89+
}
90+
91+
// uncomment this part to print table
92+
for (i = 0; i < size; i++)
93+
{
94+
for (j = 0; j <= sum/2; j++)
95+
printf ("%4d", part[i][j]);
96+
printf("\n");
97+
}
98+
99+
return part[size-1][sum/2];
100+
}
101+
102+
int main(){
103+
int arr[] = {3,1,5,9,12};
104+
int size = sizeof(arr)/sizeof(arr[0]);
105+
if(findPartition(arr,size)){
106+
printf("can be divided\n");
107+
}else{
108+
printf("cannot be divided\n");
109+
}
110+
return 0;
111+
}

nextquestions.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,8 @@ TODO:
8383
- DP question7 to be done
8484
- DP question11 (method1 naive) to be done
8585
- DP question13 and 14(printing the subsequence to be done)
86-
- https://gsamaras.wordpress.com/code/caution-when-reading-char-with-scanf-c/
86+
- https://gsamaras.wordpress.com/code/caution-when-reading-char-with-scanf-c/
87+
- DP solution extension from geeks for geeks for question17 and course sol as well
88+
- program to find fibonacci number in logn time (geeks for geeks)
89+
- DP question 19 to be done
90+

0 commit comments

Comments
 (0)