Skip to content

Commit bc48c5d

Browse files
committed
String to Integer (atoi), Longest Palindromic Substring
1 parent 77b80e2 commit bc48c5d

3 files changed

+251
-0
lines changed

C++/chapString.tex

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,254 @@ \subsubsection{相关题目}
5353
\item Add Two Numbers,见 \S \ref{sec:add-two-numbers}
5454
\myenddot
5555

56+
57+
\section{String to Integer (atoi)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
58+
\label{sec:string-to-integer}
59+
60+
61+
\subsubsection{描述}
62+
Implement \fn{atoi} to convert a string to an integer.
63+
64+
\textbf{Hint}: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.
65+
66+
\textbf{Notes}: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.
67+
68+
\textbf{Requirements for atoi}:
69+
70+
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
71+
72+
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
73+
74+
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
75+
76+
If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, \code{INT_MAX (2147483647)} or \code{INT_MIN (-2147483648)} is returned.
77+
78+
\subsubsection{分析}
79+
细节题。注意几个测试用例:
80+
\begin{enumerate}
81+
\item 不规则输入,但是有效,"-3924x8fc", " + 413",
82+
\item 无效格式," ++c", " ++1"
83+
\item 溢出数据,"2147483648"
84+
\end{enumerate}
85+
86+
\subsubsection{代码}
87+
\begin{Code}
88+
// LeetCode, String to Integer (atoi)
89+
class Solution {
90+
public:
91+
int atoi(const char *str) {
92+
int num = 0;
93+
int sign = 1;
94+
int len = strlen(str);
95+
int i = 0;
96+
97+
while (str[i] == ' ' && i < len) i++;
98+
if (str[i] == '+') i++;
99+
100+
if (str[i] == '-') {
101+
sign = -1;
102+
i++;
103+
}
104+
105+
for (; i < len; i++) {
106+
if (str[i] == ' ')
107+
break;
108+
if (str[i] < '0' || str[i] > '9')
109+
break;
110+
if (INT_MAX / 10 < num
111+
|| INT_MAX / 10 == num
112+
&& INT_MAX % 10 < (str[i] - '0')) {
113+
return sign == -1 ? INT_MIN : INT_MAX;
114+
break;
115+
}
116+
num = num * 10 + str[i] - '0';
117+
}
118+
return num * sign;
119+
}
120+
};
121+
\end{Code}
122+
123+
124+
\subsubsection{相关题目}
125+
\begindot
126+
\item
127+
\myenddot
128+
129+
130+
\section{Longest Palindromic Substring} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131+
\label{sec:longest-palindromic-substring}
132+
133+
134+
\subsubsection{描述}
135+
Given a string $S$, find the longest palindromic substring in $S$. You may assume that the maximum length of $S$ is 1000, and there exists one unique longest palindromic substring.
136+
137+
138+
\subsubsection{分析}
139+
最长回文子串,非常经典的题。
140+
141+
思路一:暴力枚举,以每个元素为中间元素,同时从左右出发,复杂度$O(n^2)$
142+
143+
思路二:记忆化搜索,复杂度$O(n^2)$。设\fn{f[i][j]} 表示[i,j]之间的最长回文子串,递推方程如下:
144+
\begin{Code}
145+
f[i][j] = if (i == j) S[i]
146+
if (S[i] == S[j] && f[i+1][j-1] == S[i+1][j-1]) S[i][j]
147+
else max(f[i+1][j-1], f[i][j-1], f[i+1][j])
148+
\end{Code}
149+
150+
思路三:动规,复杂度$O(n^2)$。设状态为\fn{f(i,j)},表示区间[i,j]是否为回文串,则状态转移方程为
151+
$$
152+
f(i,j)=\begin{cases}
153+
true & ,i=j\\
154+
S[i]=S[j] & , j = i + 1 \\
155+
S[i]=S[j] \text{ and } f(i+1, j-1) & , j > i + 1
156+
\end{cases}
157+
$$
158+
159+
思路三:Manacher’s Algorithm, 复杂度$O(n)$。详细解释见 \myurl{http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html} 。
160+
161+
162+
\subsubsection{代码}
163+
164+
\begin{Code}
165+
// LeetCode, Longest Palindromic Substring
166+
// 记忆化搜索,大集合会超时
167+
typedef string::const_iterator Iterator;
168+
169+
namespace std {
170+
template<>
171+
struct hash<pair<Iterator, Iterator>> {
172+
size_t operator()(pair<Iterator, Iterator> const& p) const {
173+
return ((size_t) &(*p.first)) ^ ((size_t) &(*p.second));
174+
}
175+
};
176+
}
177+
178+
class Solution {
179+
public:
180+
string longestPalindrome(string const& s) {
181+
cache.clear();
182+
return memoizedLongestPalindrome(begin(s), end(s));
183+
}
184+
185+
private:
186+
unordered_map<pair<Iterator, Iterator>, string> cache;
187+
188+
string longestPalindrome(Iterator first, Iterator last) {
189+
size_t length = distance(first, last);
190+
191+
if (length < 2) return string(first, last);
192+
193+
auto s = memoizedLongestPalindrome(next(first), prev(last));
194+
195+
if (s.length() == length - 2 and *first == *prev(last))
196+
return string(first, last);
197+
198+
auto s1 = memoizedLongestPalindrome(next(first), last);
199+
auto s2 = memoizedLongestPalindrome(first, prev(last));
200+
201+
// return max(s, s1, s2)
202+
if (s.size() > s1.size()) return s.size() > s2.size() ? s : s2;
203+
else return s1.size() > s2.size() ? s1 : s2;
204+
}
205+
206+
string memoizedLongestPalindrome(Iterator first, Iterator last) {
207+
auto key = make_pair(first, last);
208+
auto pos = cache.find(key);
209+
210+
if (pos != cache.end()) return pos->second;
211+
else return cache[key] = longestPalindrome(first, last);
212+
}
213+
};
214+
\end{Code}
215+
216+
\begin{Code}
217+
// LeetCode, Longest Palindromic Substring
218+
// 动规
219+
class Solution {
220+
public:
221+
string longestPalindrome(string s) {
222+
const int len = s.size();
223+
int f[len][len];
224+
memset(f, 0, len * len * sizeof(int)); //TODO: std::fill, fill_n
225+
int maxL = 1, start = 0; // 最长回文子串的长度,起点
226+
227+
for (size_t i = 0; i < s.size(); i++) {
228+
f[i][i] = 1;
229+
for (size_t j = 0; j < i; j++) { // [j, i]
230+
f[j][i] = (s[j] == s[i] && (i - j < 2 || f[j + 1][i - 1]));
231+
if (f[j][i] && maxL < (i - j + 1)) {
232+
maxL = i - j + 1;
233+
start = j;
234+
}
235+
}
236+
}
237+
return s.substr(start, maxL);
238+
}
239+
};
240+
\end{Code}
241+
242+
\begin{Code}
243+
// LeetCode, Longest Palindromic Substring
244+
// Manacher’s Algorithm
245+
class Solution {
246+
public:
247+
// Transform S into T.
248+
// For example, S = "abba", T = "^#a#b#b#a#$".
249+
// ^ and $ signs are sentinels appended to each end to avoid bounds checking
250+
string preProcess(string s) {
251+
int n = s.length();
252+
if (n == 0) return "^$";
253+
254+
string ret = "^";
255+
for (int i = 0; i < n; i++) ret += "#" + s.substr(i, 1);
256+
257+
ret += "#$";
258+
return ret;
259+
}
260+
261+
string longestPalindrome(string s) {
262+
string T = preProcess(s);
263+
int n = T.length();
264+
// 以T[i]为中心,向左/右扩张的长度,不包含T[i]自己,
265+
// 因此 P[i]是源字符串中回文串的长度
266+
int *P = new int[n];
267+
int C = 0, R = 0;
268+
269+
for (int i = 1; i < n - 1; i++) {
270+
int i_mirror = 2 * C - i; // equals to i' = C - (i-C)
271+
272+
P[i] = (R > i) ? min(R - i, P[i_mirror]) : 0;
273+
274+
// Attempt to expand palindrome centered at i
275+
while (T[i + 1 + P[i]] == T[i - 1 - P[i]])
276+
P[i]++;
277+
278+
// If palindrome centered at i expand past R,
279+
// adjust center based on expanded palindrome.
280+
if (i + P[i] > R) {
281+
C = i;
282+
R = i + P[i];
283+
}
284+
}
285+
286+
// Find the maximum element in P.
287+
int maxLen = 0;
288+
int centerIndex = 0;
289+
for (int i = 1; i < n - 1; i++) {
290+
if (P[i] > maxLen) {
291+
maxLen = P[i];
292+
centerIndex = i;
293+
}
294+
}
295+
delete[] P;
296+
297+
return s.substr((centerIndex - 1 - maxLen) / 2, maxLen);
298+
}
299+
};
300+
\end{Code}
301+
302+
303+
\subsubsection{相关题目}
304+
\begindot
305+
\item
306+
\myenddot
Binary file not shown.

0 commit comments

Comments
 (0)