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