diff --git a/算法问题选编/二叉树.md b/算法问题选编/二叉树.md index 74ecac8..825e8af 100644 --- a/算法问题选编/二叉树.md +++ b/算法问题选编/二叉树.md @@ -162,7 +162,7 @@ struct SBinaryTreeNode // a node of the binary tree -#### 怎样编写一个程序,把一个有序整数数组放到二叉树中? +#### 把一个有序整数数组放到二叉树中? 分析:本题考察二叉搜索树的建树方法,简单的递归结构。 @@ -195,9 +195,9 @@ struct TreeNode -#### 递归和非递归俩种方法实现二叉树的前序遍历。 - +#### 俩种方法实现二叉树的前序遍历。 +递归和非递归 #### 恢复树结构 diff --git a/算法问题选编/字符串.md b/算法问题选编/字符串.md index 0100287..9e9ef0e 100644 --- a/算法问题选编/字符串.md +++ b/算法问题选编/字符串.md @@ -2,78 +2,94 @@ 字符串常见的问题: -单词反转 -回文判断 -字符串的压缩 -字符串的排列和组合 +* 单词反转 +* 回文判断 +* 字符串的压缩 +* 字符串的排列和组合 -字符串比较 -是否是子串 +* 字符串比较 +* 子串 -翻转句子中单词的顺序。 +#### 翻转句子中单词的顺序 + 题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。句子中单词以空格符隔开。 为简单起见,标点符号和普通字母一样处理。 例如输入“I am a student.”,则输出“student. a am I”。 -分析 +``` char *revert(const char *source,char *dest); +``` -思路一:反向拷贝 -思路二:原地逆序,字符串2边的字符逐个交换 +思路一:反向拷贝 +思路二:原地逆序,字符串2边的字符逐个交换 思路三: 针对不允许临时空间的情况,也就是字符交换不用临时空间,可以使用的方法有: + 1. 异或操作 2. 也就是2个整数相互交换一个道理 + +``` char a = 'a', b = 'b'; a = a + b; b = a - b; a = a - b; +``` 类似的题目还有: 不开辟用于交换数据的临时空间,如何完成字符串的逆序(在技术一轮面试中,有些面试官会这样问) 用C语言实现一个revert函数,它的功能是将输入的字符串在原串上倒序后返回。 -按单词逆序 。如 “this is a sentence。” 逆序就是 “.sentence a is this” +#### 按单词逆序 + +如 “this is a sentence。” 逆序就是 “.sentence a is this” 思路: + 1. 先按单词逆序, 2. 对1)的结果,对整个句子逆序 -判断字符粗是否是回文 +#### 判断字符串是否是回文 + 分析: 2个指针,一头一尾,逐个比较,都相同就是回文 +#### 请编写能直接实现strstr()函数功能的代码。 - - -请编写能直接实现strstr()函数功能的代码。 +``` string.h char *strstr(const char *haystack, const char * needle); //返回第一次出现子串的地址,否则返回0 +``` +#### 编写strcpy 函数 -编写strcpy 函数。已知strcpy 函数的原型是 +已知strcpy 函数的原型是: +``` char *strcpy(char *strDest, const char *strSrc); +``` 其中strDest 是目的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数 -在字符串中删除特定的字符。 -题目:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。 - -例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.”。 +#### 在字符串中删除特定的字符 +题目:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.”。 +``` char *delete(char *source,const char *del); +``` 分析:这是一道微软面试题。在微软的常见面试题中,与字符串相关的题目占了很大的一部分, 因为写程序操作字符串能很好的反映我们的编程基本功。 +#### 只出现一次的字符 -题目:在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。 +在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。 分析:这道题是2006年google的一道笔试题。 - +``` char first_appear_only_once(const char *source) +``` + 思路一: 蛮力统计, O(n^2)复杂度 思路二: 使用hash表,2次扫描,第一次建立hash表 key为字符,value为出现次数;第二次扫描找到第一个value为1的key,时间复杂度O(n) @@ -85,56 +101,62 @@ hash表长度 256,字符直接作为key值 -题目:匹配兄弟字符串 +#### 匹配兄弟字符串 + 如果两个字符串的字符一样,但是顺序不一样,被认为是兄弟字符串,问如何在迅速匹配兄弟字符串(如,bad和adb就是兄弟字符串)。思路:判断各自素数乘积是否相等。更多方法请参见:http://blog.csdn.net/v_JULY_v/article/details/6347454。 +``` BOOL isBrother(const char *first,const char *secd) +``` -思路一: 循环匹配 指数级复杂度 +思路一: 循环匹配 指数级复杂度 思路二: 利用质数,平方和比较,但这样必须是2个串的长度要一样,需要的空间比较大,最多256个字节 - +#### 字符串的集合合并 给定一个字符串的集合,格式如:{aaa bbb ccc}, {bbb ddd},{eee fff},{ggg},{ddd hhh}要求将其中交集不为空的集合合并,要求合并完成后的集合之间无交集,例如上例应输出{aaa bbb ccc ddd hhh},{eee fff}, {ggg}。 + 给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。 +#### 统计文章里单词出现的次数 设计相应的数据结构和算法,尽量高效的统计一片英文文章(总单词数目)里出现的所有英文单词,按照在文章中首次出现的顺序打印输出该单词和它的出现次数。 - +``` +void statistics(char *string) void statistics(FILE *fd) +``` +#### 字符串原地压缩 -字符串原地压缩 题目描述:“eeeeeaaaff" 压缩为 "e5a3f2",请编程实现。 分析,主要问题在于字符串的移动 +``` char *compress(const char *src,char *dest) +``` - -字符串匹配实现 +#### 字符串匹配实现 请以俩种方法,回溯与不回溯算法实现。 -实现一个挺高级的字符匹配算法: -给一串很长字符串,要求找到符合要求的字符串,例如目的串:123 -1******3***2 ,12*****3这些都要找出来 -其实就是类似一些和谐系统。。。。。 +实现一个高级的字符匹配算法 +#### 对称子字符串的最大长度 - -对称子字符串的最大长度 -题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度。 -比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4。 +题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度。比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4。 分析:可能很多人都写过判断一个字符串是不是对称的函数,这个题目可以看成是该函数的加强版。 + +``` int max_symmetrical_char_length(const char *scr); +``` 思路一:蛮力法,3重循环(类似 求子数组的最大和 fmax(i,j)问题), fmax(i,j)区间i,j是最长的对称字符 @@ -143,28 +165,34 @@ int max_symmetrical_char_length(const char *scr); 思路三: 有个O(n)复杂度的 http://www.jb51.net/article/48090.htm +#### 小写字母排在大写字母的前面 -有一个由大小写组成的字符串,现在需要对他进行修改,将其中的所有小写字母排在答谢字母的前面(大写或小写字母之间不要求保持原来次序),如有可能尽量选择时间和空间效率高的算法 c语言函数原型void proc(char *str) 也可以采用你自己熟悉的语言 +有一个由大小写组成的字符串,现在需要对他进行修改,将其中的所有小写字母排在大写字母的前面(大写或小写字母之间不要求保持原来次序),如有可能尽量选择时间和空间效率高的算法 c语言函数原型: + +``` +void proc(char *str) +``` + +#### 字符串中找出连续最长的数字串 + +写一个函数,功能: + +在字符串中找出连续最长的数字串,并把这个串的长度返回,并把这个最长数字串赋值给其中一个函数参数outputstr所指内存。 + +例如:"abcd12345ed125ss123456789"的首地址传给intputstr后,函数将返回9,outputstr所指的值为123456789 + +它的原形是 + +``` +int continumax(char *outputstr,char *intputstr) +``` +#### 左旋转字符串 -写一个函数,它的原形是int continumax(char *outputstr,char *intputstr) -功能: -在字符串中找出连续最长的数字串,并把这个串的长度返回, -并把这个最长数字串付给其中一个函数参数outputstr所指内存。 - -例如:"abcd12345ed125ss123456789"的首地址传给intputstr后,函数将返回9, -outputstr所指的值为123456789 - - - - - - -题目:左旋转字符串 -定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。 +>字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。 如把字符串abcdef左旋转2位得到字符串cdefab。请实现字符串左旋转的函数。 要求时间对长度为n的字符串操作的复杂度为O(n),辅助内存为O(1)。 @@ -174,14 +202,14 @@ outputstr所指的值为123456789 -有n个长为m+1的字符串, -如果某个字符串的最后m个字符与某个字符串的前m个字符匹配,则两个字符串可以联接, -问这n个字符串最多可以连成一个多长的字符串,如果出现循环,则返回错误。 +有n个长为m+1的字符串,如果某个字符串的最后m个字符与某个字符串的前m个字符匹配,则两个字符串可以联接,问这n个字符串最多可以连成一个多长的字符串,如果出现循环,则返回错误。 -3)设计一个系统处理词语搭配问题,比如说 中国 和人民可以搭配, +#### 设计一个系统处理词语搭配问题 + +设计一个系统处理词语搭配问题,比如说 中国 和人民可以搭配, 则中国人民 人民中国都有效。要求: *系统每秒的查询数量可能上千次; @@ -193,28 +221,32 @@ outputstr所指的值为123456789 -4.删除字符串中的数字并压缩字符串。 +#### 删除字符串中的数字并压缩字符串 + 如字符串”abc123de4fg56”处理后变为”abcdefg”。注意空间和效率。 (下面的算法只需要一次遍历,不需要开辟新空间,时间复杂度为O(N)) -求两个串中的第一个最长子串(神州数码以前试题)。 +#### 求两个串中的第一个最长子串 + 如"abractyeyt","dgdsaeactyey"的最大子串为"actyet"。 -删除串中指定的字符 -(做此题时,千万不要开辟新空间,否则面试官可能认为你不适合做嵌入式开发) +#### 删除串中指定的字符 + +``` char *delete_character(char *src , char target) +``` -替换空格 +#### 替换空格 实现一个函数,把每个空格替换成 "%20",如输入“we are happy”,则输出“we%20are%20happy” -寻址重复的元素 +#### 寻址重复的元素 a~z包括大小写与0~9组成的N个数,用最快的方式把其中重复的元素挑出来。 hash方法。hash[128], O(N)复杂度 @@ -222,88 +254,78 @@ hash方法。hash[128], O(N)复杂度 -编码实现字符串转整型的函数(实现函数atoi的功能),据说是神州数码笔试题。如将字符 -串 ”+123”123, ”-0123”-123, “123CS45”123, “123.45CS”123, “CS123.45”0 +#### 编码实现字符串转整型的函数 + +也就是实现函数atoi的功能,如将字符串 ”+123”123, ”-0123”-123, “123CS45”123, “123.45CS”123, “CS123.45”0 -1.给出一个函数来复制两个字符串A和B。 -字符串A的后几个字节和字符串B的前几个字节重叠。 -分析:记住,这种题目往往就是考你对边界的考虑情况。 +#### 给出一个函数来复制两个字符串A和B + +字符串A的后几个字节和字符串B的前几个字节重叠。这种题目往往就是考你对边界的考虑情况。 -已知一个字符串,比如asderwsde,寻找其中的一个子字符串比如sde的个数, -如果没有返回0,有的话返回子字符串的个数。 + +#### 子串匹配的个数 + +已知一个字符串,比如asderwsde,寻找其中的一个子字符串比如sde的个数,如果没有返回0,有的话返回子字符串的个数。 +``` char *sub_str_count(const char *src, const char *substr, int *count) +``` +#### 求最大连续递增数字串 -函数将字符串中的字符'*'移到串的前部分, -前面的非'*'字符后移,但不能改变非'*'字符的先后顺序,函数返回串中字符'*'的数量。 -如原始串为:ab**cd**e*12, -处理后为*****abcde12,函数并返回值为5。(要求使用尽量少的时间和辅助空间) +(如“ads3sl456789DF3456ld345AA”中的“456789”) - -求最大连续递增数字串(如“ads3sl456789DF3456ld345AA”中的“456789”) +``` int continuousnum(const char *input, char *output) +``` - -最长公共字串。 - -题目:如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中, - -则字符串一称之为字符串二的子串。 - -注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中。 - - - - - -最长公共子串问题 +#### 最长公共子串问题 请编写一个函数,输入两个字符串,求它们的最长公共子串,并打印出最长公共子串。 -例如:输入两个字符串BDCABA和ABCBDAB,字符串BCBA和BDAB都是是它们的最长公共子串, - -则输出它们的长度4,并打印任意一个子串。 +例如:输入两个字符串BDCABA和ABCBDAB,字符串BCBA和BDAB都是是它们的最长公共子串,则输出它们的长度4,并打印任意一个子串。 如"abccade","dgcadde"的最大子串为"cad" -分析:求最长公共子串(Longest Common Subsequence, LCS)是一道非常经典的动态规划题, +分析:求最长公共子串(Longest Common Subsequence, LCS)是一道非常经典的动态规划题,因此一些重视算法的公司像MicroStrategy都把它当作面试题。 -因此一些重视算法的公司像MicroStrategy都把它当作面试题。 - +``` int longest_common_subsequence(const char *s1,const char *s2, char *common) - +``` -字符串的排列。 +#### 字符串的排列 -题目:输入一个字符串,打印出该字符串中字符的所有排列。 - -例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。输入字符串 abcca,则输出由 a,b,c排列出来的所有字符串,字符出现个数不变 +题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。输入字符串 abcca,则输出由 a,b,c排列出来的所有字符串,字符出现个数不变 分析:这是一道很好的考查对递归理解的编程题 -简单的回溯就可以实现了。当然排列的产生也有很多种算法,去看看组合数学, -还有逆序生成排列和一些不需要递归生成排列的方法。 +简单的回溯就可以实现了。当然排列的产生也有很多种算法,去看看组合数学,还有逆序生成排列和一些不需要递归生成排列的方法。 -印象中Knuth的第一卷里面深入讲了排列的生成。 -这些算法的理解需要一定的数学功底, -也需要一定的灵感,有兴趣最好看看。 +>印象中Knuth的第一卷里面深入讲了排列的生成。这些算法的理解需要一定的数学功底,也需要一定的灵感,有兴趣最好看看。 +#### ? - +给一串很长字符串,要求找到符合要求的字符串,例如目的串:123 ,1******3***2 ,12*****3这些都要找出来 +其实就是类似一些和谐系统。。。。。 + + +#### ? + +函数将字符串中的字符'*'移到串的前部分,前面的非'*'字符后移,但不能改变非'*'字符的先后顺序,函数返回串中字符'*'的数量。 +如原始串为:ab**cd**e*12,处理后为*****abcde12,函数并返回值为5。(要求使用尽量少的时间和辅助空间)