-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Day-61 One DP problem and finished chap 2 of CTCI2
- Loading branch information
Showing
5 changed files
with
503 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
253 changes: 253 additions & 0 deletions
253
cracking_the_coding_interview_problems/2-6-palindrome.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
/** | ||
* Cracking the coding interview edition 6 | ||
* Implement a function to check if a list is a palindrome. | ||
* | ||
* Approach 1: Reverse the half the list and compare with other half. | ||
* Approach 2: Iterative Approach | ||
* - Push half the list in stack, | ||
* - Compare the rest of the list by popping off from the stack | ||
* Approach 3: Recursive Approach | ||
*/ | ||
|
||
#include <iostream> | ||
#include <stack> | ||
|
||
struct Node { | ||
char data; | ||
Node * next; | ||
Node ( char c ) : data{ c }, next{ nullptr } { } | ||
}; | ||
|
||
/** | ||
* [insert helper routine to insert new node at head] | ||
* @param head [current head of the list] | ||
* @param c [new node's data] | ||
*/ | ||
void insert( Node * & head, char c ) { | ||
Node * newNode = new Node(c); | ||
newNode->next = head; | ||
head = newNode; | ||
} | ||
|
||
/** | ||
* [printList = helper routine to print the list] | ||
* @param head [head of the list] | ||
*/ | ||
void printList( Node * head ) { | ||
while( head ) { | ||
std::cout << head->data << "-->"; | ||
head = head->next; | ||
} | ||
std::cout << "nullptr" << std::endl; | ||
} | ||
|
||
|
||
/** | ||
* [reversedList helper routine to reverse a list] | ||
* @param head [head of current list] | ||
* @return [reversed list's head] | ||
*/ | ||
void reverse( Node * & head ) { | ||
if ( head == nullptr || (head && (head->next == nullptr))){ | ||
return; | ||
} | ||
Node * newHead = nullptr; | ||
Node * nextNode = nullptr; | ||
while ( head ) { | ||
nextNode = head->next; | ||
head->next = newHead; | ||
newHead = head; | ||
head = nextNode; | ||
} | ||
head = newHead; | ||
} | ||
|
||
|
||
/** | ||
* [isPallindromeIter1 - Iteratively determine if list is palindrome using reversing the list] | ||
* @param head [Head node of the list] | ||
* @return [True if list is palindrome, false if not] | ||
*/ | ||
bool isPalindromeIter1( Node * head ) { | ||
|
||
// if list is empty or just contains one node. | ||
if ( head == nullptr || head->next == nullptr ) { | ||
return true; | ||
} | ||
|
||
//step1 figure out middle node. | ||
Node * ptr1 = head; | ||
Node * ptr2 = head; | ||
Node * middleNode = nullptr; | ||
|
||
while( ptr2 && ptr1 && ptr1->next) { | ||
ptr1 = ptr1->next->next; | ||
ptr2 = ptr2->next; | ||
} | ||
|
||
//in case of odd number of nodes, skip the middle one | ||
if ( ptr1 && ptr1->next == nullptr ) { | ||
ptr2 = ptr2->next; | ||
} | ||
|
||
|
||
//reverse the second half of the list | ||
reverse(ptr2); | ||
|
||
middleNode = ptr2; | ||
// now compare the two halves | ||
ptr1 = head; | ||
|
||
while( ptr1 && ptr2 && ptr1->data == ptr2->data ) { | ||
ptr1 = ptr1->next; | ||
ptr2 = ptr2->next; | ||
} | ||
|
||
//reverse the list again. | ||
reverse(middleNode); | ||
|
||
if ( ptr2 == nullptr ) { | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
/** | ||
* [isPalindromeIter2 - Iteratively determine if list is palindrome using a stack] | ||
* @param head [Head node of the list] | ||
* @return [True if list is palindrome, false if not] | ||
*/ | ||
bool isPalindromeIter2( Node * head ) { | ||
// if list is empty or just contains one node. | ||
if ( head == nullptr || head->next == nullptr ) { | ||
return true; | ||
} | ||
|
||
Node * ptr1 = head; | ||
Node * ptr2 = head; | ||
|
||
//pushing the first half of list to stack. | ||
std::stack<Node*> nodeStack; | ||
|
||
while( ptr2 && ptr1 && ptr1->next ) { | ||
ptr1 = ptr1->next->next; | ||
nodeStack.push(ptr2); | ||
ptr2 = ptr2->next; | ||
} | ||
|
||
//in case of odd number of nodes, skip the middle one | ||
if ( ptr1 && ptr1->next == nullptr ) { | ||
ptr2 = ptr2->next; | ||
} | ||
|
||
// Now compare the other half of the list with nodes | ||
// we just pushed in stack | ||
|
||
while(!nodeStack.empty() && ptr2) { | ||
Node * curr = nodeStack.top(); | ||
nodeStack.pop(); | ||
if (curr->data != ptr2->data) { | ||
return false; | ||
} | ||
ptr2 = ptr2->next; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
|
||
/** | ||
* [isPalindromeRecurHelper - Recursive approach to determine if list is palindrome] | ||
* Idea is to use two pointers left and right, we move left and right to reduce | ||
* problem size in each recursive call, for a list to be palindrome, we need these two | ||
* conditions to be true in each recursive call. | ||
* a. Data of left and right should match. | ||
* b. Remaining Sub-list is palindrome. | ||
* We are using function call stack for right to reach at last node and then compare | ||
* it with first node (which is left). | ||
* @param left [left pointer of sublist] | ||
* @param right [right pointer of sublist] | ||
* @return [true if sublist is palindrome, false if not] | ||
*/ | ||
bool isPalindromeRecurHelper( Node * & left, Node * right ) { | ||
//base case Stop when right becomes nullptr | ||
if ( right == nullptr ) { | ||
return true; | ||
} | ||
|
||
//rest of the list should be palindrome | ||
bool isPalindrome = isPalindromeRecurHelper(left, right->next); | ||
if (!isPalindrome) { | ||
return false; | ||
} | ||
|
||
// check values at current node. | ||
isPalindrome = ( left->data == right->data ); | ||
|
||
// move left to next for next call. | ||
left = left->next; | ||
|
||
return isPalindrome; | ||
} | ||
|
||
bool isPalindromeRecur( Node * head ) { | ||
return isPalindromeRecurHelper(head, head); | ||
} | ||
|
||
|
||
int main() | ||
{ | ||
Node * head1 = nullptr; | ||
insert( head1, 'a' ); | ||
insert( head1, 'b' ); | ||
insert( head1, 'c' ); | ||
insert( head1, 'c' ); | ||
insert( head1, 'b' ); | ||
insert( head1, 'a' ); | ||
std::cout << "List 1: "; | ||
printList( head1 ); | ||
if ( isPalindromeRecur( head1 ) ) { | ||
std::cout << "List 1 is pallindrome list\n"; | ||
} else { | ||
std::cout << "List 1 is not a pallindrome list\n"; | ||
} | ||
std::cout << "List 1: "; | ||
printList( head1 ); | ||
|
||
Node * head2 = nullptr; | ||
insert( head2, 'r'); | ||
insert( head2, 'a'); | ||
insert( head2, 'd'); | ||
insert( head2, 'a'); | ||
insert( head2, 'r'); | ||
std::cout << "List 2: "; | ||
printList( head2 ); | ||
|
||
if ( isPalindromeRecur( head2 ) ) { | ||
std::cout << "List 2 is pallindrome list\n"; | ||
} else { | ||
std::cout << "List 2 is not a pallindrome list\n"; | ||
} | ||
|
||
std::cout << "List 2: "; | ||
printList( head2 ); | ||
|
||
Node * head = nullptr; | ||
insert( head, 'a' ); | ||
insert( head, 'b' ); | ||
insert( head, 'c' ); | ||
insert( head, 'b' ); | ||
insert( head, 'd' ); | ||
std::cout << "List 3: "; | ||
printList( head ); | ||
|
||
if ( isPalindromeRecur( head ) ) { | ||
std::cout << "List 3 is pallindrome list\n"; | ||
} else { | ||
std::cout << "List 3 is not a pallindrome list\n"; | ||
} | ||
std::cout << "List 3: "; | ||
printList( head ); | ||
return 0; | ||
} |
98 changes: 98 additions & 0 deletions
98
cracking_the_coding_interview_problems/2-7-intersection.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/** | ||
* Cracking the coding interview edition 6 | ||
* Problem 2.7 Intersection | ||
* Given two linked lists, if they both intersect at some point. | ||
* Find out the intersecting point else return nullptr. | ||
* Intersection is defined based on reference not value. | ||
*/ | ||
|
||
#include <iostream> | ||
#include <cmath> | ||
|
||
struct Node { | ||
int data; | ||
Node * next; | ||
Node( int d ) : data{ d }, next{ nullptr } { } | ||
}; | ||
|
||
/** | ||
* [printList Helper routine to print list] | ||
* @param head [head of the list] | ||
*/ | ||
void printList( Node * head ) | ||
{ | ||
while( head ) { | ||
std::cout << head->data << "-->"; | ||
head = head->next; | ||
} | ||
std::cout << "NULL" << std::endl; | ||
} | ||
|
||
int listLen( Node * head ) | ||
{ | ||
int count = 0; | ||
while( head ) { | ||
head = head->next; | ||
count++; | ||
} | ||
return count; | ||
} | ||
|
||
/** | ||
* [intersectionPoint Returns the point of intersection of two lists] | ||
* @param head1 [ head of list 1 ] | ||
* @param head2 [ head of list 2 ] | ||
* @return [ Intersecting node, if lists intersect, else nullptr] | ||
*/ | ||
Node * intersectionPoint( Node * head1, Node * head2 ) | ||
{ | ||
int len1 = listLen(head1); | ||
int len2 = listLen(head2); | ||
//figure out the bigger list ( and smaller ) | ||
//ptr points to bigger list, let us move the difference | ||
//between the two. | ||
Node * ptr1 = ( len1 > len2 ) ? head1 : head2; | ||
Node * ptr2 = ( len1 > len2 ) ? head2 : head1; | ||
int i = 0; | ||
while ( i < std::abs(len1 - len2) && ptr1 ) { | ||
ptr1 = ptr1->next; | ||
++i; | ||
} | ||
//Now we have equal nodes to travel on both the nodes | ||
// traversing and comparing the pointers. | ||
|
||
while( ptr1 && ptr2 ) { | ||
if ( ptr1 == ptr2 ) { | ||
return ptr1; | ||
} | ||
ptr1 = ptr1->next; | ||
ptr2 = ptr2->next; | ||
} | ||
return nullptr; | ||
} | ||
|
||
|
||
int main() | ||
{ | ||
Node * list1 = new Node(3); | ||
list1->next = new Node(6); | ||
list1->next->next = new Node(9); | ||
list1->next->next->next = new Node(12); | ||
list1->next->next->next->next = new Node(15); | ||
list1->next->next->next->next->next = new Node(18); | ||
|
||
Node * list2 = new Node(7); | ||
list2->next = new Node(10); | ||
list2->next->next = list1->next->next->next; | ||
|
||
printList(list1); | ||
printList(list2); | ||
|
||
Node * intersectingNode = intersectionPoint( list1 , list2 ); | ||
if (intersectingNode) { | ||
std::cout << "Intersecting Node of lists is :" << intersectingNode->data << std::endl; | ||
} else { | ||
std::cout << "Lists do not interset" << std::endl; | ||
} | ||
return 0; | ||
} |
Oops, something went wrong.