Skip to content

Commit

Permalink
Merge branch 'C_CPP' into C_CPP
Browse files Browse the repository at this point in the history
  • Loading branch information
anushkaa-02 authored Oct 13, 2021
2 parents a3e1a3d + 8efcf10 commit a5bb78b
Show file tree
Hide file tree
Showing 123 changed files with 9,758 additions and 45 deletions.
126 changes: 126 additions & 0 deletions C_CPP/Algorithmic Approaches/Backtracking/backtracking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Backtracking Algorithms

### What is meant by "Backtracking" ?
- Backtracking means to retrace one's steps.
- Backtracking Algorithm is an algorithm implemented using recursion for solving problems.
- Backtracking technique is simply based upon the idea that you take a step and then if that step is not fulfilling the constraints
then you take that step back and choose another step,Means you backtrack.

**For Example**
You encountered with four gates with different paths ,and you don't know which gate will take you to the correct position,
So what you will do is open the gates one by one if you get the right one then you will go ahead and if not then you will move back and choose another gate,
Means you just backtrack from using that step and then choose another step.


### Question on ***Backtracking***

**1 Rat in a Maze**
A square matrix named maze is given to you.The blocks which can be used are denoted by 1 and rest by 0
**Brute force Approach**
In backtracking we used to try each and every **possible solution** to reach our destination and at the end we find the correct solution.
In the same manner for this question we have two directions in which the rat can move,**forward** and **downward**.
Here to reach from the source to destination the rat will first try to move in the forward direction if the block ahead will be 1 then that solution will be
added to the solution,else the rat will backtrack from that block to its initial position and try another option i.e. move downwards.
### Algorithm
- Take the matrix maze as input
- Make a solutions array an initialize with 0
- traverse through the maze and check whether the block is safe or not
- Mark 1 for those blocks which are in your solution
- If any block takes you to wrong position then set that block to 0 again

### Code
```c++

#include <iostream>
#include<vector>
using namespace std;


bool issafe (vector < vector < int >>maze, int x, int y, int m, int n)
{ // the boolean function issafe is checking whether the block at x,y index is safe or not { //check whether the index lie inside the maze and is it 1 or not
if (x >= 0 && x < m && y >= 0 && y < n && maze[x][y] == 1)
return true;
return false;
}

bool solution (vector < vector < int >>maze, int x, int y, vector < vector < int >>&ans, int m, int n) //here x and y are storing the current position of rat
{
if (x == m - 1 && y == n - 1 && maze[x][y] == 1)
{
ans[x][y] = 1;
return true;
}
if (issafe (maze, x, y, m, n) == true)
{
if (ans[x][y] == 1)
return false;
ans[x][y] = 1;

if (solution (maze, x + 1, y, ans, m, n) == true) //if the solution for moving one block forward is true then return true
return true;
if (solution (maze, x, y + 1, ans, m, n) == true) //if the solution for moving one block downward is true then return true
return true;
ans[x][y] = 0; //if either of them is not true means the current block is not the correct solution so backtrack from it by marking it 0
return false;
}

return false;
}

int main ()
{

int m, n;
cout << "Enter number of rows\n";
cin >> m;
cout << "Enter number of columns\n";
cin >> n;
vector < vector < int >>maze (n, vector < int >(m));
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
int element;
cin >> element;
maze[i][j] = element;
}
}
vector < vector < int >>sol (n, vector < int >(m));
for (int row = 0; row < m; row++)
{
for (int col = 0; col < n; col++)
{
sol[row][col] = 0; // initialized each element of solution to 0 initially
}
}
bool answer = solution (maze, 0, 0, sol, m, n); //solution is taking the maze and solution array
// and starting and ending positions in the maze i.e. 0,0
if (answer == false) // if false is returned by solution it means no path to destination exists
cout << "Solution does not exists";
else
{
for (int i = 0; i < sol.size (); i++)
{
for (int j = 0; j < sol[i].size (); j++)
cout << sol[i][j];
cout << "\n";
}
}
return 0;
}
```
**Input**
>Enter number of rows
>2
>Enter number of columns
>2
>1 1 0 1
**Output:**
>1 1
>0 1
### Complexity Analysis:
**Time Complexity: O(2<sup>(n<sup>2</sup>)</sup>).**
**Space Complexity: O(n<sup>2</sup>).**
1 change: 1 addition & 0 deletions C_CPP/Algorithmic Approaches/Backtracking/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[Backtracking Algorithm](./Algorithmic%20Approaches/Backtracking/backtracking.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Longest Palindromic Substring Using Brute Force Approach
# Brute Force
- A Brute Force Algorithm is a straight-forward approach to a problem i.e the first method or algorithm which come in our mind to solve a particular problem. In this we try every possibility rather than going for advance techniques to improve efficiency.
# Longest Palindromic Substring
Task: Given a string, find the longest substring which is palindrome.

Approach: The simple/brute force approach will be to check for each substring whether the substring is a palindrome or not. To do this, we will run three loops, the outer two loops will pick up each substring one by one by modifying its start and end index (here i and j), the inner loop will check whether the selected substring is a palindrome or not. If yes and also the length of that substring is greater than the previous then we will update the values of start_index and length.

After coming out of all loops we will print the longest substring via using start index and length and then we will return length of the longest substring.

# Code of Longest Palindromic Substring in C++
```cpp
/*
Given a string, find the longest substring which is palindrome.
*/
#include<bits/stdc++.h>
using namespace std;

//Function to get length of longest palindromic substring and to print that substring
int Longest_Palindromic_substr(string str)
{
//This will store maximum length so far
int length=0;

//Starting index of substring
int start_index=0;

//Loops to regulate size of substring
for(int i=0;i<str.length();i++)
{
for(int j=i;j<str.length();j++)
{
int flag=1;

//To check if it is a palindrome or not
for(int k=0;k<(j-i+1)/2;k++)
if(str[i+k]!=str[j-k])
flag=0;
//If it is a palindrome and its length is greater than the current length then update the values
if(flag && (j-i+1)>length)
{
start_index=i;
length=j-i+1;
}
}
}
//Print the substring
cout << "Longest palindromic substring is: ";
for(int i=start_index;i<=start_index+length-1;i++)
cout << str[i];

return length;
}

//Main Function
int main()
{
string str;

//Take string from the user
cout << "Enter string: ";
cin >> str;

cout << "\nLength of longest palindromic substring is: " << Longest_Palindromic(str);

return 0;
}
```
# Input/Output Example
<b>Example 1-</b>
<b>Input:</b>
Enter string: babad
<b>Output:</b>
Longest palindromic substring is: bab
Length of longest palindromic substring is: 3
<b>Example 2-</b>
<b>Input:</b>
Enter string: cbbd
<b>Output:</b>
Longest palindromic substring is: bb
Length of longest palindromic substring is: 2
# Time And Space Complexity
Time Complexity: O(n<sup>3</sup>)
Space Complexity: O(1)
1 change: 1 addition & 0 deletions C_CPP/Algorithmic Approaches/Brute Force/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- [Longest Palindromic Substring](Longest_Palindromic_Substring.md)
159 changes: 159 additions & 0 deletions C_CPP/Algorithmic Approaches/Divide & Conquer/DAC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Divide and Conquer Algorithm
As its name suggest in this algorithmic approach we divide the given problem in to sub problem and then we solve each sub problem recursively and then we combine the result of each sub problem to get the solution.<br>
there are many algorith which are based on this technique but from those some of the important algorithm are:-<br>
1. Binary search
2. Merge sort
3. Find max and min
4. Quick sort
## Binary seearch using DAC
```cpp
//binary search using DAC techinque
#include<bits/stdc++.h>
using namespace std;
int binary_DAC(int arr[],int i , int j,int key)
{ if(i==j){
if(key==arr[i])
return i;
else
return -1;
}
int mid=(i+j)/2; //Divide step
if(key==arr[mid])
return mid;
if(key<arr[mid])
return binary_DAC(arr,i,mid-1,key); // solving each sub problem recursively
else
return binary_DAC(arr,mid+1,j,key);
}
int main()
{ int arr[]={10,20};
int size=sizeof(arr)/sizeof(int),key=10;
int index=binary_DAC(arr,0,size-1,key);
if(index==-1)
cout<<"element not found";
else
cout<<"element is found at the index "<<index;
return 0;
}
```
**Note** :- The combine step is not mandatory in DAC approach as u can see there is no combine step in this problem.
## Merge sort using DAC
```cpp
#include<bits/stdc++.h>
using namespace std;
void merge(int arr[],int beg,int mid,int end)
{ int l1=mid-beg+1,l2=end-mid;
int left[l1],right[l2];
for(int m=0 ; m<l1 ; m++) left[m]=arr[beg+m];
for(int m=0 ; m<l2 ; m++) right[m]=arr[mid+m+1];
int m=0,n=0,k=beg;
while(m<l1 && n<l2)
{ if(left[m]<right[n])
arr[k++]=left[m++];
else
arr[k++]=right[n++];
}
while(m<l1) {arr[k++]=left[m++];}
while(n<l2) {arr[k++]=right[n++];}
}
void mergesort(int arr[],int i,int j)
{ if(i<j){
int mid=(i+j)/2; // divide step
mergesort(arr,i,mid); // solving each sub problem
mergesort(arr,mid+1,j); // solving each sub problem
merge(arr,i,mid,j); // combine step
}
else
return;
}
int main()
{ int arr[]={21,3,10,11,50,14,23};
int size=sizeof(arr)/sizeof(int);
mergesort(arr,0,size-1);
for(auto it:arr)
cout<<it<<" ";
return 0;
}
```
This algorithmic approach has a time complixity of O(n log n) and space complixity of O(n). Majority portion of its time complixity is in **combine step** and this is one of the difference in the merge sort and quick sort as in quick sort major portion of its time complixity is in **divide step**.
## Find max and min in an array using DAC
```cpp
//use divide and conqure technique to find the maximum and minimum element in an array
#include<bits/stdc++.h>
using namespace std;
struct node{
int max,min;
};
node dac_max_min(int arr[],int i,int j)
{ struct node s1,s2,s3;
if(i==j){
s1.max=s1.min=arr[i];
return s1;
}
else if(j-i==1)
{ s1.max=arr[i]>arr[j]?arr[i]:arr[j];
s1.min=arr[i]<arr[j]?arr[i]:arr[j];
return s1;
}
else
{ int mid=(i+j)/2; // divide step
s2=dac_max_min(arr,i,mid); // solving each sub problem recursively
s3=dac_max_min(arr,mid+1,j); // solving each sub problem recursively
s1.max=s2.max>s3.max?s2.max:s3.max; // combine step
s1.min=s2.min<s3.min?s2.min:s3.min; // combine step
return s1;
}
}
int main()
{ int arr[20]={-2,5,1,-10,20,13,75,12,52,11};
int i=0,size=sizeof(arr)/sizeof(int);
struct node result=dac_max_min(arr,i,size-1);
cout<<"maximun element is: "<<result.max<<endl;
cout<<"minimun element is: "<<result.min;
return 0;
}
```
## Quick sort using DAC
```cpp
// use quick sort (DAC) to sort an array
#include<bits/stdc++.h>
using namespace std;
void swap( int *a , int *b)
{ int temp;
temp=*a;
*a=(*b);
*b=temp;
}
int partition(int arr[],int beg,int end)
{ int i=beg-1,j=beg,pivot;
pivot=arr[end];
while(j<end)
{ if(arr[j]<pivot)
{ i++;
swap(&arr[i],&arr[j]);
}
j++;
}
swap(&arr[i+1],&arr[end]);
return (i+1);
}
void quicksort(int arr[],int beg,int end)
{ if(beg<end)
{ int q=partition(arr,beg,end); // divide step
quicksort(arr,beg,q-1); // solving each sub problem recursively
quicksort(arr,q+1,end); //solving each sub problem recursively
}
}
int main()
{ int arr[]={10,60,12,56,54,25,41};
int size=sizeof(arr)/sizeof(int);
quicksort(arr,0,size-1);
for(auto it:arr)
cout<<it<<" ";
return 0;
}
```
In this approach <br>
best time complexity is O(n log n)<br>
average case O(n log n)<br>
worst case O(n^2)
Loading

0 comments on commit a5bb78b

Please sign in to comment.