完成几道字符串题目
This commit is contained in:
@@ -108,14 +108,21 @@
|
||||
* 快速排序
|
||||
* SPFA(shortest path faster algorithm) 单元最短路径算法
|
||||
* 快递选择SELECT
|
||||
|
||||
|
||||
|
||||
## 算法设计思想
|
||||
|
||||
为了更简洁的形式设计和藐视算法,在算法设计时又常常采用递归技术,用递归描述算法。
|
||||
|
||||
|
||||
|
||||
|
||||
## 海量数据处理
|
||||
|
||||
* 分而治之/Hash映射 + hash统计/trie树/红黑树/二叉搜索树 + 堆排序/快速排序/归并排序
|
||||
* 双层桶划分
|
||||
* Bloom filter 、Bitmap
|
||||
* Trie树/数据库/倒排索引
|
||||
* 外排序
|
||||
* 分布处理之 Hadoop/Mapreduce
|
||||
|
||||
|
||||
## 算法设计思想
|
||||
|
||||
* 迭代法
|
||||
* 穷举搜索法
|
||||
* 递推法
|
||||
@@ -125,13 +132,9 @@
|
||||
* 回溯
|
||||
* 分治算法
|
||||
|
||||
http://www.chinaunix.net/old_jh/23/437639.html
|
||||
|
||||
|
||||
|
||||
## 推荐阅读
|
||||
|
||||
|
||||
### 刷题必备
|
||||
|
||||
《剑指offer》
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
## 海量数据处理
|
||||
|
||||
|
||||
海量处理问题常用的分析解决问题的思路是:
|
||||
|
||||
* 分而治之/Hash映射 + hash统计/trie树/红黑树/二叉搜索树 + 堆排序/快速排序/归并排序
|
||||
* 双层桶划分
|
||||
* Bloom filter 、Bitmap
|
||||
* Trie树/数据库/倒排索引
|
||||
* 外排序
|
||||
* 分布处理之 Hadoop/Mapreduce
|
||||
|
||||
|
||||
### 分而治之/Hash映射 + hash统计/trie树/红黑树/二叉搜索树 + 堆排序/快速排序/归并排序
|
||||
|
||||
|
||||
### 双层桶划分
|
||||
|
||||
|
||||
### Bloom filter 、Bitmap
|
||||
|
||||
|
||||
### Trie树/数据库/倒排索引
|
||||
|
||||
|
||||
### 外排序
|
||||
|
||||
|
||||
### 分布处理之 Hadoop/Mapreduce
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
##堆和栈
|
||||
|
||||
|
||||
栈的数据结构结构
|
||||
栈的数据结构
|
||||
|
||||
```
|
||||
typede int Value;
|
||||
@@ -23,7 +23,7 @@ Value pop(Stack);
|
||||
|
||||
```
|
||||
|
||||
队列的数据结构结构
|
||||
队列的数据结构
|
||||
|
||||
```
|
||||
typede int Value;
|
||||
|
||||
+209
-96
@@ -42,98 +42,83 @@ char *revert_by_word(const char *source,char *dest){
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
类似的题目还有:
|
||||
|
||||
不开辟用于交换数据的临时空间,如何完成字符串的逆序(在技术一轮面试中,有些面试官会这样问)
|
||||
不开辟用于交换数据的临时空间,如何完成字符串的逆序(在技术一轮面试中,有些面试官会这样问)
|
||||
用C语言实现一个revert函数,它的功能是将输入的字符串在原串上倒序后返回。
|
||||
|
||||
|
||||
#### 按单词逆序
|
||||
|
||||
如 “this is a sentence。” 逆序就是 “.sentence a is this”
|
||||
思路:
|
||||
|
||||
1. 先按单词逆序,
|
||||
2. 对1)的结果,对整个句子逆序
|
||||
|
||||
|
||||
#### 判断字符串是否是回文
|
||||
|
||||
分析: 2个指针,一头一尾,逐个比较,都相同就是回文
|
||||
|
||||
|
||||
#### 请编写能直接实现strstr()函数功能的代码。
|
||||
|
||||
```
|
||||
//返回第一次出现子串的地址,否则返回0
|
||||
string.h char *strstr(const char *haystack, const char * needle);
|
||||
/*
|
||||
* eg acdeedca
|
||||
* @ret 0 success , -1 fail
|
||||
*/
|
||||
int is_huiwen(const char *source){
|
||||
if (source == NULL || source == '\0') return -1;
|
||||
char *head = source;
|
||||
char *tail = source;
|
||||
while(*tail != '\0'){
|
||||
tail++;
|
||||
}
|
||||
tail--;
|
||||
|
||||
while(head < tail){
|
||||
if (*head != *tail){
|
||||
return -1;
|
||||
}
|
||||
head++;
|
||||
tail--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 编写strcpy 函数
|
||||
|
||||
已知strcpy 函数的原型是:
|
||||
```
|
||||
char *strcpy(char *strDest, const char *strSrc);
|
||||
```
|
||||
其中strDest 是目的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数
|
||||
|
||||
|
||||
#### 在字符串中删除特定的字符
|
||||
|
||||
题目:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.”。
|
||||
```
|
||||
char *delete(char *source,const char *del);
|
||||
```
|
||||
|
||||
分析:这是一道微软面试题。在微软的常见面试题中,与字符串相关的题目占了很大的一部分,
|
||||
因为写程序操作字符串能很好的反映我们的编程基本功。
|
||||
|
||||
|
||||
#### 只出现一次的字符
|
||||
|
||||
在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。
|
||||
分析:这道题是2006年google的一道笔试题。
|
||||
在一个字符串中找到第一个只出现一次的字符。如输入ahbaccdeff,则输出h。
|
||||
|
||||
```
|
||||
char first_appear_only_once(const char *source)
|
||||
char char_first_appear_once(const char *source)
|
||||
```
|
||||
|
||||
思路一: 蛮力统计, O(n^2)复杂度
|
||||
思路一: 蛮力统计, O(n^2)复杂度
|
||||
思路二: 使用hash表,2次扫描,第一次建立hash表 key为字符,value为出现次数;第二次扫描找到第一个value为1的key,时间复杂度O(n)
|
||||
|
||||
思路二: 使用hash表,2次扫描,第一次建立hash表 key为字符,value为出现次数;第二次扫描找到第一个value为1的key,时间复杂度O(n)
|
||||
hash表长度 256,字符直接作为key值。需要注意的是 char 的范围是 -128~127,unsigned char 才是0~255
|
||||
|
||||
hash表长度 256,字符直接作为key值
|
||||
|
||||
|
||||
示例代码:
|
||||
|
||||
```
|
||||
char char_first_appear_once(const unsigned char *source){
|
||||
int hash[256]={0};
|
||||
char *tmp = source;
|
||||
if (tmp == NULL) return '\0';
|
||||
while(*tmp != '\0'){
|
||||
hash[*tmp]++;
|
||||
tmp++;
|
||||
}
|
||||
|
||||
tmp = source;
|
||||
while(*tmp != '\0'){
|
||||
if (hash[*tmp] == 1) return *tmp;
|
||||
tmp++;
|
||||
}
|
||||
return '\0';
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
题目扩展:这里的字符换成整数,整数数量几十TB,海量数据处理,显然hash方法不可能,没有那么大得内容
|
||||
|
||||
|
||||
|
||||
#### 匹配兄弟字符串
|
||||
|
||||
如果两个字符串的字符一样,但是顺序不一样,被认为是兄弟字符串,问如何在迅速匹配兄弟字符串(如,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的前几个字节重叠。
|
||||
|
||||
|
||||
#### 统计文章里单词出现的次数
|
||||
|
||||
设计相应的数据结构和算法,尽量高效的统计一片英文文章(总单词数目)里出现的所有英文单词,按照在文章中首次出现的顺序打印输出该单词和它的出现次数。
|
||||
@@ -143,6 +128,140 @@ void statistics(char *string)
|
||||
void statistics(FILE *fd)
|
||||
```
|
||||
|
||||
|
||||
延伸:
|
||||
|
||||
如果是海量数据里面统计top-k次数的单词呢?
|
||||
|
||||
|
||||
#### 替换空格
|
||||
|
||||
实现一个函数,把每个空格替换成 "%20",如输入“we are happy”,则输出“we%20are%20happy”
|
||||
|
||||
```
|
||||
char *replce_blank(char *source)
|
||||
```
|
||||
|
||||
主要问题是一个字符替换成3个字符,替换后的字符串比原串长。
|
||||
如果想要在原串上直接修改,就不能顺序替换。且原串的空间应该足够大,能容纳替换变长以后的字符串。如果空间不够,就要新建一块空间来保存替换的结果了。这里假设空间足够
|
||||
|
||||
1. 第一遍扫描,统计空格个数 n, 替换后的字符串长度 = 原长度+2*n
|
||||
2. 从后向前扫描字符串,挪动每个字符的位置。注意碰到空格的地方
|
||||
|
||||
|
||||
```
|
||||
char *replace_blank(char *source){
|
||||
int count = 0;
|
||||
char *tail = source;
|
||||
if (source == NULL) return NULL;
|
||||
while(*tail != '\0'){
|
||||
if (*tail == ' ') count++;
|
||||
tail++;
|
||||
}
|
||||
|
||||
while(count){
|
||||
if(*tail != ' '){
|
||||
*(tail+2*count) = *tail;
|
||||
}else{
|
||||
*(tail+2*count) = '0';
|
||||
*(tail+2*count-1) = '2';
|
||||
*(tail+2*count-2) = '%';
|
||||
count--;
|
||||
}
|
||||
tail--;
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 小写字母排在大写字母的前面
|
||||
|
||||
有一个由大小写组成的字符串,现在需要对他进行修改,将其中的所有小写字母排在大写字母的前面(大写或小写字母之间不要求保持原来次序),如有可能尽量选择时间和空间效率高的算法 c语言函数原型:
|
||||
|
||||
```
|
||||
void proc(char *str)
|
||||
```
|
||||
分析:
|
||||
|
||||
比如:HaJKPnobAACPc,要小写字母前面且不要求保存顺序,可以是:anobcHJKPAACP
|
||||
|
||||
小写字母 a~z 的 ASCII码值 是 ,A~Z 的 ASCII码值 是 ;
|
||||
|
||||
|
||||
示例代码
|
||||
|
||||
```
|
||||
void proc(char *str){
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 实现字符串转整型的函数
|
||||
|
||||
也就是实现函数atoi的功能,这道题目考查的就是对各种情况下异常处理。比如
|
||||
|
||||
正/负数,"-432"
|
||||
浮点数,"43.2344"
|
||||
溢出,"32111111112222222222222222222222222222222"
|
||||
非法,"2123des" 0
|
||||
NULL/空串,这时候返回值0
|
||||
|
||||
以"213"分析转换成证书的过程。3+1*10+2*100,思路是:每扫描到一个字符,把之前得到的数字*10,再加上当前的数字
|
||||
|
||||
```
|
||||
int atoi(const char *str){
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 匹配兄弟字符串
|
||||
|
||||
如果两个字符串的字符一样,但是顺序不一样,被认为是兄弟字符串,问如何在迅速匹配兄弟字符串(如,bad和adb就是兄弟字符串)。
|
||||
|
||||
思路:判断各自素数乘积是否相等。更多方法请参见:http://blog.csdn.net/v_JULY_v/article/details/6347454。
|
||||
|
||||
```
|
||||
int isBrother(const char *first,const char *secd)
|
||||
```
|
||||
|
||||
思路一: 循环匹配 指数级复杂度
|
||||
思路二: 利用质数,平方和比较,但这样必须是2个串的长度要一样,需要的空间比较大,最多256个字节。
|
||||
|
||||
|
||||
|
||||
示例代码:
|
||||
|
||||
```
|
||||
int isBrother(const char *first,const char *secd){
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 字符串的集合合并
|
||||
|
||||
给定一个字符串的集合,格式如:{aaa bbb ccc}, {bbb ddd},{eee fff},{ggg},{ddd hhh}要求将其中交集不为空的集合合并,要求合并完成后的集合之间无交集,例如上例应输出{aaa bbb ccc ddd hhh},{eee fff}, {ggg}。
|
||||
|
||||
|
||||
|
||||
#### 在字符串中删除特定的字符
|
||||
|
||||
题目:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.”。
|
||||
```
|
||||
char *delete_occurence(char *source,const char *del);
|
||||
```
|
||||
|
||||
1. 蛮力法。 遍历字符串,每个字符去删除字符串集合中查找,有就删除
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#### 字符串原地压缩
|
||||
|
||||
题目描述:“eeeeeaaaff" 压缩为 "e5a3f2",请编程实现。
|
||||
@@ -153,6 +272,7 @@ char *compress(const char *src,char *dest)
|
||||
|
||||
|
||||
#### 字符串匹配实现
|
||||
|
||||
请以俩种方法,回溯与不回溯算法实现。
|
||||
|
||||
|
||||
@@ -176,13 +296,6 @@ int max_symmetrical_char_length(const char *scr);
|
||||
思路三: 有个O(n)复杂度的 http://www.jb51.net/article/48090.htm
|
||||
|
||||
|
||||
#### 小写字母排在大写字母的前面
|
||||
|
||||
有一个由大小写组成的字符串,现在需要对他进行修改,将其中的所有小写字母排在大写字母的前面(大写或小写字母之间不要求保持原来次序),如有可能尽量选择时间和空间效率高的算法 c语言函数原型:
|
||||
|
||||
```
|
||||
void proc(char *str)
|
||||
```
|
||||
|
||||
#### 字符串中找出连续最长的数字串
|
||||
|
||||
@@ -199,8 +312,6 @@ int continumax(char *outputstr,char *intputstr)
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
#### 左旋转字符串
|
||||
|
||||
>字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。
|
||||
@@ -211,7 +322,7 @@ int continumax(char *outputstr,char *intputstr)
|
||||
|
||||
|
||||
|
||||
|
||||
#### n个字符串联接
|
||||
|
||||
有n个长为m+1的字符串,如果某个字符串的最后m个字符与某个字符串的前m个字符匹配,则两个字符串可以联接,问这n个字符串最多可以连成一个多长的字符串,如果出现循环,则返回错误。
|
||||
|
||||
@@ -238,31 +349,13 @@ int continumax(char *outputstr,char *intputstr)
|
||||
(下面的算法只需要一次遍历,不需要开辟新空间,时间复杂度为O(N))
|
||||
|
||||
|
||||
|
||||
#### 删除串中指定的字符
|
||||
|
||||
```
|
||||
char *delete_character(char *src , char target)
|
||||
```
|
||||
|
||||
|
||||
#### 替换空格
|
||||
实现一个函数,把每个空格替换成 "%20",如输入“we are happy”,则输出“we%20are%20happy”
|
||||
|
||||
|
||||
|
||||
#### 寻址重复的元素
|
||||
a~z包括大小写与0~9组成的N个数,用最快的方式把其中重复的元素挑出来。
|
||||
|
||||
hash方法。hash[128], O(N)复杂度
|
||||
|
||||
|
||||
|
||||
|
||||
#### 编码实现字符串转整型的函数
|
||||
|
||||
也就是实现函数atoi的功能,如将字符串 ”+123”123, ”-0123”-123, “123CS45”123, “123.45CS”123, “CS123.45”0
|
||||
|
||||
|
||||
|
||||
|
||||
#### 给出一个函数来复制两个字符串A和B
|
||||
@@ -320,6 +413,26 @@ int longest_common_subsequence(const char *s1,const char *s2, char *common)
|
||||
>印象中Knuth的<TAOCP>第一卷里面深入讲了排列的生成。这些算法的理解需要一定的数学功底,也需要一定的灵感,有兴趣最好看看。
|
||||
|
||||
|
||||
|
||||
|
||||
#### 请编写能直接实现strstr()函数功能的代码。
|
||||
|
||||
```
|
||||
//返回第一次出现子串的地址,否则返回0 string.h
|
||||
char *strstr(const char *haystack, const char * needle);
|
||||
```
|
||||
|
||||
|
||||
#### 编写strcpy 函数
|
||||
|
||||
已知strcpy 函数的原型是:
|
||||
```
|
||||
char *strcpy(char *strDest, const char *strSrc);
|
||||
```
|
||||
其中strDest 是目的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数
|
||||
|
||||
|
||||
|
||||
#### ?
|
||||
|
||||
给一串很长字符串,要求找到符合要求的字符串,例如目的串:123 ,1******3***2 ,12*****3这些都要找出来
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "stdio.h"
|
||||
|
||||
char char_first_appear_once(const unsigned char *source){
|
||||
int hash[256]={0};
|
||||
char *tmp = source;
|
||||
if (tmp == NULL) return '\0';
|
||||
while(*tmp != '\0'){
|
||||
hash[*tmp]++;
|
||||
tmp++;
|
||||
}
|
||||
|
||||
tmp = source;
|
||||
while(*tmp != '\0'){
|
||||
if (hash[*tmp] == 1) return *tmp;
|
||||
tmp++;
|
||||
}
|
||||
return '\0';
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
char *test = "77ah-ba-ccdeff";
|
||||
char c = char_first_appear_once(test);
|
||||
printf("c=%c\n", c);/* c = 'h'*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "stdio.h"
|
||||
|
||||
char *replace_blank(char *source){
|
||||
int count = 0;
|
||||
char *tail = source;
|
||||
if (source == NULL) return NULL;
|
||||
while(*tail != '\0'){
|
||||
if (*tail == ' ') count++;
|
||||
tail++;
|
||||
}
|
||||
|
||||
while(count){
|
||||
if(*tail != ' '){
|
||||
*(tail+2*count) = *tail;
|
||||
}else{
|
||||
*(tail+2*count) = '0';
|
||||
*(tail+2*count-1) = '2';
|
||||
*(tail+2*count-2) = '%';
|
||||
count--;
|
||||
}
|
||||
tail--;
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
char str[100]="we are happy";
|
||||
printf("ret=%s\n",replace_blank(str));
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user