Skip to content

Commit 6c777f1

Browse files
committed
Day-12 Cracking the coding interview 1-4
1 parent 47474b9 commit 6c777f1

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* Cracking the coding interview edition 6
3+
* Given a string, write a function to check if it is a permutation of a pallindrome.
4+
*
5+
* Solution Philosophy:
6+
* For a string to be pallindrome, it should be able to spelled backward and forward the same.
7+
* Therefore the chars in string should fit one of the two possibilities:
8+
* - Each char appear even number of times in the string ( even length string )
9+
* - Each char should appear even number of times, except just one char ( odd length string )
10+
*
11+
* We won't care about the case of the letter
12+
*/
13+
14+
#include <iostream>
15+
16+
17+
/*
18+
* Helper routine to return an frequency Table index
19+
*
20+
*/
21+
22+
int getCharIndex( char c )
23+
{
24+
int idx = -1;
25+
if ( c >= 'a' && c <= 'z' )
26+
{
27+
idx = c - 'a';
28+
}
29+
else if ( c >= 'A' && c <= 'Z' )
30+
{
31+
idx = c - 'A';
32+
}
33+
return idx;
34+
}
35+
36+
/*
37+
* Function : countFrequency
38+
* Args : input string, an array of int
39+
* Return : Void, array of int will populate each letter's frequency in string.
40+
*/
41+
42+
void countFrequency( const std::string & str, int *frequency )
43+
{
44+
int idx;
45+
for (const char & c : str)
46+
{
47+
idx = getCharIndex(c);
48+
if ( idx != -1 )
49+
{
50+
++frequency[idx];
51+
}
52+
}
53+
}
54+
55+
56+
/*
57+
* Function : isPermutePallindrome
58+
* Args : input string
59+
* Return : returns true if is possible that one of the permutations of input string can be a pallindrome.
60+
* else return false
61+
*/
62+
63+
bool isPermutationOfPallindrome1( const std::string & str )
64+
{
65+
int frequency[ 26 ] = { 0 };
66+
countFrequency( str, frequency );
67+
68+
/*
69+
* We will check here that letter frequencies are all even or all even except one odd.
70+
*/
71+
bool oddAppeared = false;
72+
std::cout << std::endl;
73+
for ( int i = 0 ; i < 26; ++i ) {
74+
if ( frequency[i] % 2 && oddAppeared ) {
75+
return false;
76+
} else if ( frequency[i] % 2 && !oddAppeared ) {
77+
oddAppeared = true;
78+
}
79+
}
80+
return true;
81+
}
82+
83+
84+
/*
85+
* Approach 2:
86+
* Let us optimize above function instead of taking another pass let us do it
87+
* in one go, we will count odd chars as we go along, if we are left with
88+
* more that 0 or 1, then the input string can't have pallindrome permutation
89+
*/
90+
91+
bool isPermutationOfPallindrome2( const std::string & str )
92+
{
93+
int oddCount = 0;
94+
int frequency[26] = { 0 };
95+
int idx = 0;
96+
for ( const char & c : str )
97+
{
98+
idx = getCharIndex(c);
99+
if ( idx != -1 )
100+
{
101+
++frequency[idx];
102+
if ( frequency[idx] % 2 )
103+
{
104+
++oddCount;
105+
} else {
106+
--oddCount;
107+
}
108+
}
109+
}
110+
return (oddCount <= 1);
111+
}
112+
113+
/*
114+
* Approach 3
115+
* let us represent each char with a bit in a bitvector
116+
* Each time a char appears in the string we toggle the
117+
* respective bit, if we are left with more than 1 bit
118+
* in the bit vector, the string can not have a pallidrome
119+
* permutation.
120+
*
121+
*/
122+
123+
/*
124+
* helper function to toggle a bit in the integer
125+
*/
126+
127+
int toggle( int bitVector, int index )
128+
{
129+
if ( index < 0 )
130+
return bitVector;
131+
132+
int mask = 1 << index;
133+
//if bit is not set
134+
if ( (bitVector & mask ) == 0 )
135+
{
136+
bitVector |= mask;
137+
} else { //if bit is set
138+
bitVector &= ~mask;
139+
}
140+
return bitVector;
141+
}
142+
143+
/*
144+
* Helper functiont to find if a single bit is set
145+
* i.e. if bitVector is a multiple of power of 2
146+
*/
147+
148+
bool isExactlyOneBitSet( int bitVector )
149+
{
150+
return ( (bitVector & (bitVector - 1)) == 0 );
151+
}
152+
153+
/*
154+
* Third approach solution
155+
* toggle bit represent the respective char
156+
* for each appearance in the string.
157+
*/
158+
159+
bool isPermutationOfPallindrome3( const std::string & str )
160+
{
161+
int bitVector = 0;
162+
int id = 0;
163+
for ( const char & c : str )
164+
{
165+
id = getCharIndex(c);
166+
bitVector = toggle (bitVector, id );
167+
}
168+
return ( bitVector == 0 || isExactlyOneBitSet(bitVector) );
169+
}
170+
171+
int main()
172+
{
173+
std::string str("Tact Coa");
174+
std::cout << "Does \"" << str << "\" has a string whose permutation is a pallindrome? "
175+
<< "( 1 for true, 0 for false ) : ";
176+
std::cout << "Approach 1:" << isPermutationOfPallindrome1( str ) << std::endl;
177+
std::cout << "Approach 2:" << isPermutationOfPallindrome2( str ) << std::endl;
178+
std::cout << "Approach 3:" << isPermutationOfPallindrome3( str ) << std::endl;
179+
180+
181+
std::string str1("A big Cat");
182+
std::cout << "Does \"" << str1 << "\" has a string whose permutation is a pallindrome? "
183+
<< "( 1 for true, 0 for false ) : ";
184+
std::cout << "Approach 1:" << isPermutationOfPallindrome1( str1 ) << std::endl;
185+
std::cout << "Approach 2:" << isPermutationOfPallindrome2( str1 ) << std::endl;
186+
std::cout << "Approach 3:" << isPermutationOfPallindrome3( str1 ) << std::endl;
187+
188+
189+
std::string str2("Aba cbc");
190+
std::cout << "Does \"" << str2 << "\" has a string whose permutation is a pallindrome? "
191+
<< "( 1 for true, 0 for false ) : ";
192+
std::cout << "Approach 1:" << isPermutationOfPallindrome1( str2 ) << std::endl;
193+
std::cout << "Approach 2:" << isPermutationOfPallindrome2( str2 ) << std::endl;
194+
std::cout << "Approach 3:" << isPermutationOfPallindrome3( str2 ) << std::endl;
195+
return 0;
196+
}

0 commit comments

Comments
 (0)