Skip to content

Commit

Permalink
将字符串这章移动到前面,增加atoi等题目,修复morris遍历的BUG
Browse files Browse the repository at this point in the history
  • Loading branch information
soulmachine committed Sep 23, 2013
1 parent 4187f57 commit 33656b5
Show file tree
Hide file tree
Showing 6 changed files with 396 additions and 22 deletions.
2 changes: 1 addition & 1 deletion C++/ACM-cheat-sheet.tex
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

\include{chapProgrammingTrick}
\include{chapLinearList}
\include{chapString}
\include{chapStackAndQueue}
\include{chapTree}
\include{chapSearching}
Expand All @@ -50,7 +51,6 @@
\include{chapGraph}
\include{chapMath}
\include{chapBigInt}
\include{chapString}
\include{chapFundamental}

\appendix % 开始附录,章用字母编号
Expand Down
187 changes: 187 additions & 0 deletions C++/chapString.tex
Original file line number Diff line number Diff line change
@@ -1,13 +1,200 @@
\chapter{字符串}


\section{字符串API} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
面试中经常会出现,现场编写 \fn{strcpy, strlen, strstr, atoi} 等库函数的题目。这类题目看起来简单,实则难度很大,区分都很高,很容易考察出你的编程功底,是面试官的最爱。


\subsection{strlen}


\subsubsection{描述}
实现 \fn{strlen},获取字符串长度,函数原型如下:
\begin{Code}
size_t strlen(const char *str);
\end{Code}


\subsubsection{分析}



\subsubsection{代码}
\begin{Code}
size_t strlen(const char *str) {
const char *s;
for (s = str; *s; ++s) {}
return(s - str);
}
\end{Code}


\subsection{strcpy}


\subsubsection{描述}
实现 \fn{strcpy},字符串拷贝函数,函数原型如下:
\begin{Code}
char* strcpy(char *to, const char *from);
\end{Code}


\subsubsection{分析}



\subsubsection{代码}
\begin{Code}
char* strcpy(char *to, const char *from) {
assert(to != NULL && from != NULL);
char *p = to;
while ((*p++ = *from++) != '\0')
;
return to;
}
\end{Code}


\subsection{strstr}


\subsubsection{描述}
实现 \fn{strstr},子串查找函数,函数原型如下:
\begin{Code}
char * strstr(const char *haystack, const char *needle);
\end{Code}


\subsubsection{分析}
暴力算法的复杂度是 $O(m*n)$,代码如下。其他算法见第\S \ref{sec:substring-search}节 “子串查找”。


\subsubsection{代码}
\begin{Code}
char *strstr(const char *haystack, const char *needle) {
// if needle is empty return the full string
if (!*needle) return (char*) haystack;

const char *p1;
const char *p2;
const char *p1_advance = haystack;
for (p2 = &needle[1]; *p2; ++p2) {
p1_advance++; // advance p1_advance M-1 times
}

for (p1 = haystack; *p1_advance; p1_advance++) {
char *p1_old = (char*) p1;
p2 = needle;
while (*p1 && *p2 && *p1 == *p2) {
p1++;
p2++;
}
if (!*p2) return p1_old;

p1 = p1_old + 1;
}
return NULL;
}
\end{Code}


\subsubsection{相关题目}
与本题相同的题目:
\begindot
\item LeetCode Implement strStr(), \myurl{http://leetcode.com/oldoj\#question_28}
\myenddot

与本题相似的题目:
\begindot
\item
\myenddot


\subsection{atoi}
\label{sec:string-to-integer}


\subsubsection{描述}
实现 \fn{atoi},将一个字符串转化为整数,函数原型如下:
\begin{Code}
int atoi(const char *str);
\end{Code}


\subsubsection{分析}
注意,这题是故意给很少的信息,让你来考虑所有可能的输入。

来看一下\fn{atoi}的官方文档(\myurl{http://www.cplusplus.com/reference/cstdlib/atoi/}),看看它有什么特性:

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.

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.

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.

If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, \fn{INT_MAX (2147483647)} or \fn{INT_MIN (-2147483648)} is returned.

注意几个测试用例:
\begin{enumerate}
\item 不规则输入,但是有效,"-3924x8fc", " + 413",
\item 无效格式," ++c", " ++1"
\item 溢出数据,"2147483648"
\end{enumerate}


\subsubsection{代码}
\begin{Code}
int atoi(const char *str) {
int num = 0;
int sign = 1;
const int len = strlen(str);
int i = 0;

while (str[i] == ' ' && i < len) i++;

if (str[i] == '+') i++;

if (str[i] == '-') {
sign = -1;
i++;
}

for (; i < len; i++) {
if (str[i] < '0' || str[i] > '9')
break;
if (num > INT_MAX / 10 ||
(num == INT_MAX / 10 &&
(str[i] - '0') > INT_MAX % 10)) {
return sign == -1 ? INT_MIN : INT_MAX;
}
num = num * 10 + str[i] - '0';
}
return num * sign;
}
\end{Code}


\subsubsection{相关题目}
与本题相同的题目:
\begindot
\item LeetCode String to Integer (atoi), \myurl{http://leetcode.com/oldoj\#question_8}
\myenddot

与本题相似的题目:
\begindot
\item
\myenddot


\section{字符串排序} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\section{单词查找树} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\section{子串查找} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\label{sec:substring-search}

字符串的一种基本操作就是\textbf{子串查找}(substring search):给定一个长度为$N$的文本和一个长度为$M$的模式串(pattern string),在文本中找到一个与该模式相符的子字符串。

最简单的算法是暴力查找,时间复杂度是$O(MN)$。下面介绍两个更高效的算法。
Expand Down
20 changes: 10 additions & 10 deletions C++/chapTree.tex
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ \subsection{C语言实现}

if (node->right == NULL ) { /* 还没线索化,则建立线索 */
node->right = cur;
prev = cur;
/* prev = cur; 不能有这句,cur还没有被访问 */
cur = cur->left;
} else { /* 已经线索化,则访问节点,并删除线索 */
visit(cur);
Expand All @@ -450,7 +450,7 @@ \subsection{C语言实现}
while (cur != NULL ) {
if (cur->left == NULL ) {
visit(cur);
prev = cur;
prev = cur; /* cur刚刚被访问过 */
cur = cur->right;
} else {
/* 查找前驱 */
Expand All @@ -459,13 +459,13 @@ \subsection{C语言实现}
node = node->right;

if (node->right == NULL ) { /* 还没线索化,则建立线索 */
visit(cur); /* 仅这一行与中序不同 */
visit(cur); /* 仅这一行的位置与中序不同 */
node->right = cur;
prev = cur;
prev = cur; /* cur刚刚被访问过 */
cur = cur->left;
} else { /* 已经线索化,则访问节点,并删除线索 */
} else { /* 已经线索化,则删除线索 */
node->right = NULL;
prev = cur;
/* prev = cur; 不能有这句,cur已经被访问 */
cur = cur->right;
}
}
Expand All @@ -490,7 +490,7 @@ \subsection{C语言实现}
cur = &dump;
while (cur != NULL ) {
if (cur->left == NULL ) {
prev = cur;
prev = cur; /* 必须要有 */
cur = cur->right;
} else {
bt_node_t *node = cur->left;
Expand All @@ -499,12 +499,12 @@ \subsection{C语言实现}

if (node->right == NULL ) { /* 还没线索化,则建立线索 */
node->right = cur;
prev = cur;
prev = cur; /* 必须要有 */
cur = cur->left;
} else { /* 已经线索化,则访问节点,并删除线索 */
visit_reverse(cur->left, prev, visit); // call print
prev->right = NULL;
prev = cur;
prev = cur; /* 必须要有 */
cur = cur->right;
}
}
Expand Down Expand Up @@ -539,7 +539,7 @@ \subsection{C语言实现}
int (*visit)(bt_node_t*)) {
bt_node_t *p = to;
reverse(from, to);

while (1) {
visit(p);
if (p == from)
Expand Down
2 changes: 1 addition & 1 deletion C/ACM-cheat-sheet.tex
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

\include{chapProgrammingTrick}
\include{chapLinearList}
\include{chapString}
\include{chapStackAndQueue}
\include{chapTree}
\include{chapSearching}
Expand All @@ -50,7 +51,6 @@
\include{chapGraph}
\include{chapMath}
\include{chapBigInt}
\include{chapString}
\include{chapFundamental}

\appendix % 开始附录,章用字母编号
Expand Down
Loading

0 comments on commit 33656b5

Please sign in to comment.