Skip to content

Commit 377cc7f

Browse files
my solutions
1 parent ae2c3b9 commit 377cc7f

File tree

2 files changed

+477
-0
lines changed

2 files changed

+477
-0
lines changed
Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
/**
2+
* Cracking the coding interview edition 6
3+
* Implement a function to check if a list is a palindrome.
4+
*
5+
* Approach 1: Reverse the half the list and compare with other half.
6+
* Approach 2: Iterative Approach
7+
* - Push half the list in stack,
8+
* - Compare the rest of the list by popping off from the stack
9+
* Approach 3: Recursive Approach
10+
*/
11+
12+
#include <iostream>
13+
#include <stack>
14+
15+
struct Node
16+
{
17+
char data;
18+
Node *next;
19+
Node(char c) : data{c}, next{nullptr} {}
20+
};
21+
22+
/**
23+
* [insert helper routine to insert new node at head]
24+
* @param head [current head of the list]
25+
* @param c [new node's data]
26+
*/
27+
void insert(Node *&head, char c)
28+
{
29+
Node *newNode = new Node(c);
30+
newNode->next = head;
31+
head = newNode;
32+
}
33+
34+
/**
35+
* [printList = helper routine to print the list]
36+
* @param head [head of the list]
37+
*/
38+
void printList(Node *head)
39+
{
40+
while (head)
41+
{
42+
std::cout << head->data << "-->";
43+
head = head->next;
44+
}
45+
std::cout << "nullptr" << std::endl;
46+
}
47+
48+
/**
49+
* [reversedList helper routine to reverse a list]
50+
* @param head [head of current list]
51+
* @return [reversed list's head]
52+
*/
53+
void reverse(Node *&head)
54+
{
55+
if (head == nullptr || (head && (head->next == nullptr)))
56+
{
57+
return;
58+
}
59+
Node *newHead = nullptr;
60+
Node *nextNode = nullptr;
61+
while (head)
62+
{
63+
nextNode = head->next;
64+
head->next = newHead;
65+
newHead = head;
66+
head = nextNode;
67+
}
68+
head = newHead;
69+
}
70+
71+
/**
72+
* [isPallindromeIter1 - Iteratively determine if list is palindrome using reversing the list]
73+
* @param head [Head node of the list]
74+
* @return [True if list is palindrome, false if not]
75+
*/
76+
bool isPalindromeIter1(Node *head)
77+
{
78+
79+
// if list is empty or just contains one node.
80+
if (head == nullptr || head->next == nullptr)
81+
{
82+
return true;
83+
}
84+
85+
// step1 figure out middle node.
86+
Node *ptr1 = head;
87+
Node *ptr2 = head;
88+
Node *middleNode = nullptr;
89+
90+
while (ptr2 && ptr1 && ptr1->next)
91+
{
92+
ptr1 = ptr1->next->next;
93+
ptr2 = ptr2->next;
94+
}
95+
96+
// in case of odd number of nodes, skip the middle one
97+
if (ptr1 && ptr1->next == nullptr)
98+
{
99+
ptr2 = ptr2->next;
100+
}
101+
102+
// reverse the second half of the list
103+
reverse(ptr2);
104+
105+
middleNode = ptr2;
106+
// now compare the two halves
107+
ptr1 = head;
108+
109+
while (ptr1 && ptr2 && ptr1->data == ptr2->data)
110+
{
111+
ptr1 = ptr1->next;
112+
ptr2 = ptr2->next;
113+
}
114+
115+
// reverse the list again.
116+
reverse(middleNode);
117+
118+
if (ptr2 == nullptr)
119+
{
120+
return true;
121+
}
122+
else
123+
{
124+
return false;
125+
}
126+
}
127+
128+
/**
129+
* [isPalindromeIter2 - Iteratively determine if list is palindrome using a stack]
130+
* @param head [Head node of the list]
131+
* @return [True if list is palindrome, false if not]
132+
*/
133+
bool isPalindromeIter2(Node *head)
134+
{
135+
// if list is empty or just contains one node.
136+
if (head == nullptr || head->next == nullptr)
137+
{
138+
return true;
139+
}
140+
141+
Node *ptr1 = head;
142+
Node *ptr2 = head;
143+
144+
// pushing the first half of list to stack.
145+
std::stack<Node *> nodeStack;
146+
147+
while (ptr2 && ptr1 && ptr1->next)
148+
{
149+
ptr1 = ptr1->next->next;
150+
nodeStack.push(ptr2);
151+
ptr2 = ptr2->next;
152+
}
153+
154+
// in case of odd number of nodes, skip the middle one
155+
if (ptr1 && ptr1->next == nullptr)
156+
{
157+
ptr2 = ptr2->next;
158+
}
159+
160+
// Now compare the other half of the list with nodes
161+
// we just pushed in stack
162+
163+
while (!nodeStack.empty() && ptr2)
164+
{
165+
Node *curr = nodeStack.top();
166+
nodeStack.pop();
167+
if (curr->data != ptr2->data)
168+
{
169+
return false;
170+
}
171+
ptr2 = ptr2->next;
172+
}
173+
174+
return true;
175+
}
176+
177+
bool myIsPalindromeIterStack(Node *head)
178+
{
179+
// if list is empty or just contains one node.
180+
if (head == nullptr || head->next == nullptr)
181+
return true;
182+
183+
// jesli list zawiera tylko 2 elementy
184+
if (head->next->next == nullptr)
185+
return false;
186+
187+
Node *curent = head;
188+
Node *next = head->next->next;
189+
190+
std::stack<char> charStack;
191+
192+
while (next)
193+
{
194+
if (curent->data != next->data)
195+
{
196+
charStack.push(curent->data);
197+
curent = curent->next;
198+
next = next->next;
199+
}
200+
else
201+
{
202+
charStack.push(curent->data);
203+
next = curent->next->next;
204+
break;
205+
}
206+
}
207+
208+
while (next)
209+
{
210+
if (charStack.empty())
211+
return false;
212+
213+
if (charStack.top() == next->data)
214+
{
215+
charStack.pop();
216+
next = next->next;
217+
}
218+
else
219+
return false;
220+
}
221+
222+
return charStack.empty();
223+
}
224+
225+
/**
226+
* [isPalindromeRecurHelper - Recursive approach to determine if list is palindrome]
227+
* Idea is to use two pointers left and right, we move left and right to reduce
228+
* problem size in each recursive call, for a list to be palindrome, we need these two
229+
* conditions to be true in each recursive call.
230+
* a. Data of left and right should match.
231+
* b. Remaining Sub-list is palindrome.
232+
* We are using function call stack for right to reach at last node and then compare
233+
* it with first node (which is left).
234+
* @param left [left pointer of sublist]
235+
* @param right [right pointer of sublist]
236+
* @return [true if sublist is palindrome, false if not]
237+
*/
238+
bool isPalindromeRecurHelper(Node *&left, Node *right)
239+
{
240+
// base case Stop when right becomes nullptr
241+
if (right == nullptr)
242+
{
243+
return true;
244+
}
245+
246+
// rest of the list should be palindrome
247+
bool isPalindrome = isPalindromeRecurHelper(left, right->next);
248+
if (!isPalindrome)
249+
{
250+
return false;
251+
}
252+
253+
// check values at current node.
254+
isPalindrome = (left->data == right->data);
255+
256+
// move left to next for next call.
257+
left = left->next;
258+
259+
return isPalindrome;
260+
}
261+
262+
bool isPalindromeRecur(Node *head)
263+
{
264+
return isPalindromeRecurHelper(head, head);
265+
}
266+
267+
int main()
268+
{
269+
Node *head1 = nullptr;
270+
insert(head1, 'a');
271+
insert(head1, 'b');
272+
insert(head1, 'a');
273+
insert(head1, 'c');
274+
insert(head1, 'b');
275+
insert(head1, 'a');
276+
std::cout << "List 1: ";
277+
printList(head1);
278+
if (myIsPalindromeIterStack(head1))
279+
{
280+
std::cout << "List 1 is pallindrome list\n";
281+
}
282+
else
283+
{
284+
std::cout << "List 1 is not a pallindrome list\n";
285+
}
286+
287+
Node *head2 = nullptr;
288+
insert(head2, 'r');
289+
insert(head2, 'a');
290+
insert(head2, 'd');
291+
insert(head2, 'a');
292+
insert(head2, 'r');
293+
std::cout << "List 2: ";
294+
printList(head2);
295+
296+
if (myIsPalindromeIterStack(head2))
297+
{
298+
std::cout << "List 2 is pallindrome list\n";
299+
}
300+
else
301+
{
302+
std::cout << "List 2 is not a pallindrome list\n";
303+
}
304+
305+
Node *head = nullptr;
306+
insert(head, 'a');
307+
insert(head, 'b');
308+
insert(head, 'c');
309+
insert(head, 'b');
310+
insert(head, 'd');
311+
std::cout << "List 3: ";
312+
printList(head);
313+
314+
if (myIsPalindromeIterStack(head))
315+
{
316+
std::cout << "List 3 is pallindrome list\n";
317+
}
318+
else
319+
{
320+
std::cout << "List 3 is not a pallindrome list\n";
321+
}
322+
return 0;
323+
}

0 commit comments

Comments
 (0)