diff --git a/README.md b/README.md index be2f356..c7483fe 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ >算法虐我千百遍,我待算法如初恋。 + ##学习方法 1) 把所有经典算法写一遍 @@ -8,7 +9,7 @@ 3) 加入算法学习社区,相互鼓励学习 4) 看经典书籍 - + ##基本数据结构和算法 @@ -126,6 +127,10 @@ http://www.chinaunix.net/old_jh/23/437639.html ## 参考链接和学习网站 +POJ http://openjudge.cn/ +这有个POJ上的ACM训练方案 http://www.java3z.com/cwbwebhome/article/article19/res041.html + + 微软面试100题 http://blog.csdn.net/column/details/ms100.html 程序员编程艺术 http://blog.csdn.net/v_JULY_v/article/details/6460494 diff --git a/算法问题选编/堆和栈.md b/算法问题选编/堆和栈.md index e32d1bd..d8c8bb7 100644 --- a/算法问题选编/堆和栈.md +++ b/算法问题选编/堆和栈.md @@ -4,7 +4,6 @@ - 2.设计包含min函数的栈。 定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。 要求函数min、push以及pop的时间复杂度都是O(1)。 diff --git a/算法问题选编/数值问题.md b/算法问题选编/数值问题.md index 260ff8a..d5f955e 100644 --- a/算法问题选编/数值问题.md +++ b/算法问题选编/数值问题.md @@ -1,28 +1,131 @@ + + 写一个函数,检查字符是否是整数,如果是,返回其整数值。 (或者:怎样只用4行代码编写出一个从字符串到长整形的函数?) +分析: +使用递归实现 +int string_to_integer(char *s,int length) +单要思考几个问题: +1. s是空字符串 +2. s传参为非数字字符 +3. 超出整数所能表示范围 + -第12题 题目:求1+2+…+n, 要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句(A?B:C)。 +分析: +1. 不能使用循环,那就用递归 +2. 递归需要终止递归的条件判断语句,这里也不能用if,想其他办法,可以使用 || 逻辑或运输符 -28.整数的二进制表示中1的个数 +整数的二进制表示中1的个数 题目:输入一个整数,求该整数的二进制表达中有多少个1。 例如输入10,由于其二进制表示为1010,有两个1,因此输出2。 + 分析: 这是一道很基本的考查位运算的面试题。 包括微软在内的很多公司都曾采用过这道题。 +解法1:循环计数 +解法2:位运算 +解法3:num &= num-1 巧妙之处在于,对高位没有影响 +请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句 + +分析: +#define min(a,b) ((a)>(b)?(a):(b)) +#define MIN(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; }) + + + + +1024! 末尾有多少个0? + +分析: +末尾0的个数取决于2和5的个数 +能被2整除的数比能被5整除的数要多得多,因此只统计被5整除的数的个数 +?? + + + +编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列 + +分析: +char *integer_to_hex(long i); +char *integer_to_bin(long i); + +注意,转16进制中,要判断tmp[i]是否是有符号的数 +tmp[i]= tmp[i]>=0?tmp[i]:tmp[i]+16; + + + +大整数乘法(或 大整数阶乘) +请使用代码计算1234567891011121314151617181920*2019181716151413121110987654321 。 + +1. 注意结果可能超出长整形的最大范围 2^64-1 +2. 采用分治算法,将大整数相乘转换为小整数计算 + + + + +编程实现两个正整数的除法(和取模) +编程实现两个正整数的除法,当然不能用除法操作符。 +// return x/y. +int div(const int x, const int y) +{} + +1. 循环减被除数,减到不能再减,当除数很大,被除数小时,效率很低 +2. 位运算 + + + + +两个数相乘,小数点后位数没有限制,请写一个高精度算法 + + + + + + +如何求根号2的值,并且按照我的需要列出指定小数位,比如根号2是1.141 我要列出1位小数就是1.1 2位就是1.14, 1000位就是1.141...... 等。。 + +分析: +泰勒级数 +牛顿迭代法 + + + +求两个或N个数的最大公约数和最小公倍数。 + + + + + + +40、用1、2、2、3、4、5这六个数字,写一个main函数,打印出所有不同的排列, +如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连. + + + + + + + +给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), +指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。 + +比如,A=[1,0] K=21 那么输出结构应该为100。 + + 58、整数的素数和分解问题 @@ -44,40 +147,17 @@ -给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), -指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。 - -比如,A=[1,0] K=21 那么输出结构应该为100。 - - - - -请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句 - -两个数相乘,小数点后位数没有限制,请写一个高精度算法 - -编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列 - -如何求根号2的值,并且按照我的需要列出指定小数位,比如根号2是1.141 我要列出1位小数就是1.1 2位就是1.14, 1000位就是1.141...... 等。。 -求两个或N个数的最大公约数和最小公倍数。 - - - -40、用1、2、2、3、4、5这六个数字,写一个main函数,打印出所有不同的排列, -如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连. - - - -21、1024! 末尾有多少个0? - - - 30.在从1到n的正数中1出现的次数 题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。 例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次。 分析:这是一道广为流传的google面试题。 +int one_appear_count(int n); +1. 遍历1~n,统计出现1的个数;n足够大时,效率很低 +2. 分析规律 + + @@ -85,21 +165,14 @@ 说明:当然不能使用开方运算。 + 20、给定能随机生成整数1到5的函数,写出能随机生成整数1到7的函数。 -9、编程实现两个正整数的除法 -编程实现两个正整数的除法,当然不能用除法操作符。 -// return x/y. -int div(const int x, const int y) -{} - - -请使用代码计算1234567891011121314151617181920*2019181716151413121110987654321 。 diff --git a/算法问题选编/数值问题/1.c b/算法问题选编/数值问题/1.c new file mode 100644 index 0000000..67829ea --- /dev/null +++ b/算法问题选编/数值问题/1.c @@ -0,0 +1,37 @@ + +#include "stdio.h" +#include "string.h" + +int string_to_integer(char *s,int length){ + + if (length>1) + { + return s[0]=='-'?string_to_integer(s,length-1)*10-(s[length-1]-'0'):string_to_integer(s,length-1)*10+s[length-1]-'0'; + }else{ + return s[0]=='-'?-1/10:s[0]-'0'; + + } +} + +/* 问题: +1. s是空字符串 +2. s传参为非数字字符 +3. 超出整数所能表示范围 +*/ + + +int main(){ + + char *s = "4323"; + + printf("integer == %d\n",string_to_integer(s,strlen(s)) ); + printf("integer == %d\n",string_to_integer("12342",5)); + printf("integer == %d\n",string_to_integer("-11",3) ); + printf("integer == %d\n",string_to_integer("-5",2) ); + printf("integer == %d\n", string_to_integer("3",1)); + + printf("integer == %d\n", string_to_integer("abcd",4)); + printf("integer == %d\n", string_to_integer("a",1)); + + return 0; +} diff --git a/算法问题选编/数值问题/2.c b/算法问题选编/数值问题/2.c new file mode 100644 index 0000000..b8f86c9 --- /dev/null +++ b/算法问题选编/数值问题/2.c @@ -0,0 +1,23 @@ + +#include "stdio.h" + + +int factorial(int n){ + + int ret=0; + (n==0) || (ret=n+factorial(n-1)); + return ret; +} + + +int main(){ + + int n=10; + printf("factorial(10)= %d\n",factorial(10)); + printf("factorial(5)= %d\n",factorial(5)); + printf("factorial(1)= %d\n",factorial(1)); + printf("factorial(0)= %d\n",factorial(0)); + + return 0; +} + diff --git a/算法问题选编/数值问题/3.c b/算法问题选编/数值问题/3.c new file mode 100644 index 0000000..669624e --- /dev/null +++ b/算法问题选编/数值问题/3.c @@ -0,0 +1,71 @@ + +#include "stdio.h" +#include "stdlib.h" + +char *integer_to_bin(long integer){ + + int bit_num = sizeof(long)*8; + char *buffer= (char *)malloc(bit_num+1); + if (buffer==NULL) + { + return "malloc error"; + } + buffer[bit_num]='\0'; + + for (int i = 0; i < bit_num; ++i) + { + buffer[i]= integer<>(bit_num-1); + buffer[i]= buffer[i]==0?'0':'1'; + + } + return buffer; + +} + +char *integer_to_hex(long integer){ + + int bit_num=sizeof(long)*8/4; + char *buffer=(char *)malloc(bit_num+3); + buffer[0]='0'; + buffer[1]='x'; + buffer[bit_num+2]='\0'; + char *tmp=&buffer[2]; + + for (int i = 0; i < bit_num; i++) + { + tmp[i]= integer<<(i*4)>>(bit_num*4-4); + tmp[i]= tmp[i]>=0?tmp[i]:tmp[i]+16; + tmp[i]= tmp[i]<10?(tmp[i]+48):(tmp[i]-10+'A'); + } + + return buffer; +} + + +/* + +A 65 +0 48 + +*/ + + + +int main(){ + + + printf("b(11) = %s\n", integer_to_bin(11)); + printf("b(1023) = %s\n",integer_to_bin(1023) ); + printf("b(23564) = %s\n",integer_to_bin(23564) ); + + + printf("h(11) = %s\n", integer_to_hex(11)); + printf("h(1023) = %s\n",integer_to_hex(1023) ); + printf("h(23564) = %s\n",integer_to_hex(23564) ); + printf("b(11) = %x\n", 11); + printf("b(1023) = %x\n",1023 ); + printf("b(23564) = %x\n",23564 ); + + + return 0; +} \ No newline at end of file diff --git a/算法问题选编/数值问题/4-1.c b/算法问题选编/数值问题/4-1.c new file mode 100644 index 0000000..806e7d3 --- /dev/null +++ b/算法问题选编/数值问题/4-1.c @@ -0,0 +1,7 @@ +#include "stdio.h" + +int main(){ + + printf("%ld",236432123443*33453098); + return 0; +} \ No newline at end of file diff --git a/算法问题选编/数值问题/5.c b/算法问题选编/数值问题/5.c new file mode 100644 index 0000000..4df163b --- /dev/null +++ b/算法问题选编/数值问题/5.c @@ -0,0 +1,25 @@ + + +#include "stdio.h" + + +/* + + 1 是第一个元素 + 序列中元素被2或3或5整除 + +*/ +unsigned long value_in_sequence(unsigned index){ + + + + +} + + +int main(){ + + + + return 0; +} \ No newline at end of file diff --git a/算法问题选编/数值问题/6.c b/算法问题选编/数值问题/6.c new file mode 100644 index 0000000..926f346 --- /dev/null +++ b/算法问题选编/数值问题/6.c @@ -0,0 +1,70 @@ + + +#include "stdio.h" + +int binary_search_first(int *a,int length,int key){ + + int low=0; + int high = length-1; + int mid = 0; + + while(low=key)//往左找 + { + high = mid; + }else{ + + low = mid+1; + } + + } + return high; + +} + +int binary_search_last(int *a,int length,int key){ + + int low = 0; + int high = length -1; + int mid = 0; + + while(low + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + com.apple.xcode.dsym.a.out + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + dSYM + CFBundleSignature + ???? + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/算法问题选编/数值问题/a.out.dSYM/Contents/Resources/DWARF/a.out b/算法问题选编/数值问题/a.out.dSYM/Contents/Resources/DWARF/a.out new file mode 100644 index 0000000..b61ec8e Binary files /dev/null and b/算法问题选编/数值问题/a.out.dSYM/Contents/Resources/DWARF/a.out differ diff --git a/算法问题选编/数组数列问题.md b/算法问题选编/数组数列问题.md index 461e554..fb2687e 100644 --- a/算法问题选编/数组数列问题.md +++ b/算法问题选编/数组数列问题.md @@ -1,6 +1,6 @@ -3.求子数组的最大和 -题目: + +题目:求子数组的最大和 输入一个整形数组,数组里有正数也有负数。 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。 求所有子数组的和的最大值。要求时间复杂度为O(n)。 @@ -8,22 +8,38 @@ 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2, 因此输出为该子数组的和18。 +1. 蛮力法 fmax(i,j) 找出最大的值,3重循环 ,复杂度 0(n^3) +2. + + + + +最长公共子序列 (动态规划的经典题目) + -第21题 编程求解: -输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数, -使其和等于 m ,要求将其中所有的可能组合列出来. +输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来. + +print_sum_detials(int n , int sum) + +动态规划(类似背包问题) -5.查找最小的k个元素 + + + + +查找最小的k个元素 题目:输入n个整数,输出其中最小的k个。 例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。 +print_minimums(int *a,int length ,int k); + + -第14题: 题目:输入一个已经按升序排序过的数组和一个数字, 在数组中查找两个数,使得它们的和正好是输入的那个数字。 要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。 @@ -31,7 +47,7 @@ -1.给出两个集合A和B,其中集合A={name}, +给出两个集合A和B,其中集合A={name}, 集合B={age、sex、scholarship、address、...}, 要求: 问题1、根据集合A中的name查询出集合B中对应的属性信息; @@ -53,9 +69,7 @@ - - -第6题 + 给你10分钟时间,根据上排给出十个数,在其下排填出对应的十个数 要求下排每个数都是先前上排那十个数在下排出现的次数。 上排的十个数如下: @@ -76,7 +90,7 @@ -第18题: + 题目:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始, 每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。 当一个数字删除后,从被删除数字的下一个继续删除第m个数字。 @@ -91,7 +105,6 @@ -第23题: 用最简单, 最快速的方法计算出下面这个圆形是否和正方形相交。" 3D坐标系 原点(0.0,0.0,0.0) 圆形: @@ -108,7 +121,6 @@ -32. 有两个序列a,b,大小都为n,序列元素的值任意整数,无序; 要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。 例如: @@ -117,7 +129,7 @@ var b=[1, 2, 3, 4,5,40]; -2.一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值 +一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值 比如{3,2,4,3,6} 可以分成{3,2,4,3,6} m=1; {3,6}{2,4,3} m=2 {3,3}{2,4}{6} m=3 所以m的最大值为3 @@ -125,7 +137,6 @@ var b=[1, 2, 3, 4,5,40]; -36. n支队伍比赛,分别编号为0,1,2。。。。n-1,已知它们之间的实力对比关系, 存储在一个二维数组w[n][n]中,w[i][j] 的值代表编号为i,j的队伍中更强的一支。 @@ -139,7 +150,7 @@ n支队伍比赛,分别编号为0,1,2。。。。n-1,已知它们之间 -1.一个int数组,里面数据无任何限制,要求求出所有这样的数a[i], +一个int数组,里面数据无任何限制,要求求出所有这样的数a[i], 其左边的数都小于等于它,右边的数都大于等于它。 能否只用一个额外数组和少量其它空间实现。 @@ -362,14 +373,13 @@ f(n)= 1 n=1 -48.微软: 一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5} 是由{6,5,4,3,2,1}左移两位形成的,在这种数组中查找某一个数。 -67.俩个闲玩娱乐。 +俩个闲玩娱乐。 1.扑克牌的顺子 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。 2-10为数字本身,A为1,J为11,Q为12,K为13,而大小王可以看成任意数字。 @@ -451,18 +461,26 @@ double Power(double base, int exponent) 一个有序数列,序列中的每一个值都能够被2或者3或者5所整除,1是这个序列的第一个元素。求第1500个值是多少? +1,2,3,4,5,6,8,9,10,12,14,15,16,... + +1)所有的偶数都在序列中 +2)3的倍数也在序列中 +3)5的倍数也在系列中 +unsigned long value_in_sequence(int index) + +0. 2,3,5最小公倍数是30 +1. [1,30]符合条件有22个 +2. [30,60]符合条件也22个 + +第1500个: 1500/22=68余4,一个周期内的前4个数是2,3,4,5; 最终答案是`68*30+5` - - - 51.和为n连续正数序列。 - +和为n连续正数序列。 题目:输入一个正数n,输出所有和为n连续正数序列。 例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5、4-6和7-8。 -分析:这是网易的一道面试题。 @@ -496,14 +514,24 @@ double Power(double base, int exponent) -15、一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。 +一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。 设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。 复杂度最好是O(n),如果是O(n2)则不得分。 -10、在排序数组中,找出给定数字的出现次数 + + + +在排序数组中,找出给定数字的出现次数 比如 [1, 2, 2, 2, 3] 中2的出现次数是3次。 +1. 排序数组,可以使用二分查找 + +将二分操作观测到底,这样在最坏的情况下([2,2,2,2,2,2,2])都有0(lgn)复杂度 +int binary_search_first(int *a,int length,int key); +int binary_search_lash(int *a,int length,int key); + + 53、最长递增子序列 diff --git a/算法问题选编/海量数据处理.md b/算法问题选编/海量数据处理.md index 523bc68..4cf4ec2 100644 --- a/算法问题选编/海量数据处理.md +++ b/算法问题选编/海量数据处理.md @@ -16,6 +16,11 @@ 要求找出所有相反的串对,如abc和cba。 +一个文件中有40亿个整数,每个整数为四个字节,内存为1GB,写出一个算法:求出这个文件里的整数里不包含的一个整数 + +假设一个文件中有9亿条不重复的9位整数,现在要求对这个文件进行排序。 + + 2.给出一个文件,里面包含两个字段{url、size}, 即url为网址,size为对应网址访问的次数, diff --git a/算法问题选编/算法面试100题 b/算法问题选编/算法面试100题 index dec5133..2eecbab 100644 --- a/算法问题选编/算法面试100题 +++ b/算法问题选编/算法面试100题 @@ -67,6 +67,10 @@ int i=(j=4,k=8,l=16,m=32); printf(“%d”, i); 输出是多少? +逗号运算符 +(表达式1,表达式2,...,表达式n) 分别计算每个表达式,,最后表达式的值做为整个表达式的值 +所以输出是32 + diff --git a/算法问题选编/链表.md b/算法问题选编/链表.md index 2a660e3..98600e4 100644 --- a/算法问题选编/链表.md +++ b/算法问题选编/链表.md @@ -1,4 +1,5 @@ +链表常常碰到的问题有: 链表反转 链表中是否有环 @@ -10,6 +11,7 @@ + 判断俩个链表是否相交 给出俩个单向链表的头指针,比如h1,h2,判断这俩个链表是否相交。 为了简化问题,我们假设俩个链表均不带环。 @@ -38,12 +40,6 @@ struct ListNode -链表操作, -(1)单链表就地逆置, -(2)合并链表 - - - 30、微软面试题:Given a head pointer pointing to a linked list ,please write a function that sort the list in increasing order. You are not allowed to use temporary array or memory copy @@ -130,7 +126,6 @@ struct ListNode { int m_nKey; - ListNode* m_pNext; }; @@ -152,7 +147,6 @@ struct ListNode { int m_nKey; - ListNode* m_pNext; };