- 浏览: 175005 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
qjm201000:
您好,问下怎么进入后台管理啊?管理员后台管理在哪边?
Jforum的安装使用 -
yuchao86:
src/ext/thrift_protocol/modules ...
安装thrift -
灵魂工程师:
-intel-2.7/src/protocol/fastbin ...
安装thrift -
左看右看:
学习了,不错!
hbase的安装配置 -
asialee:
谢谢了,我对linux不熟悉,装了maven后也出现这样的问题 ...
permission denied的解决方法
待:strcpy strlen memcpy memset memmove atoi itoa的实现
注意时间复杂度
1.给出一个数列,找出连续相加最大的和
方法:(1)O(n) 一次扫描,如果sum<0, sum = 0. 英文数据结构书p23
(2)O(nlogn) devide and conqure 左右两边分别找最大,合并后的值,看看最后左、右、合并三个哪个最大 英文数据结构书p21
=================================================================
2.二分查找 O(logN)整个数列已经之前排过序才能二分查找。每次比较选中间这个,如果比中间这个大,则继续找右边的中间值,否则找左边. 英文数据结构书p23
=================================================================
3.各种排序算法
参考java各种排序算法http://shulin-success.iteye.com/blog/493705其中讲到各种排序算法的时间复杂度和空间复杂度。
这个也有用排序算法http://hzhping350.blog.163.com/blog/static/831207362008821102419976/
1.冒泡排序:程序见算法导论 P23底 思想:最小的先冒起来
2.插入排序:思想:就像我们抓牌,插牌一样.在数列大部分有序的情况下比快排有效。最好情况O(n)
3.希尔排序: 思想见:数据结构课件DS07_Ch06a.pps第5页
4.堆排序:把数字填入初始化堆(未排序,只是按顺序填入)-->然后调整为最小堆(或最大堆)buildHeap--->然后排序 见数据结构试卷P14页背面教你怎样buildHeap.数据结构试卷P7及背面教你怎样heapSort
5.归并排序
6.快速排序:思想:找到一个pivot,把原数据集分为两个子集,一个大于pivot,一个小于pivot。pivot的位置就定了,在小于集(pivot)大于集.
7.桶排序:把区间[0,1)划分为n个相同大小的子区间(即桶),先对各个桶中的数进行排序,然后按桶的次序列出数字即可。需额外空间O(n),在数符合均匀分布的情况下,O(n)
3)总结:
——按平均的时间性能来分:
1)时间复杂度为O(nlogn)的方法有:快速排序、堆排序和归并排序,其中以快速排序为最好;
2)时间复杂度为O(n2)的有:直接插入排序、起泡排序和简单选择排序,其中以直接插入为最好,特 别是对那些对关键字近似有序的记录序列尤为如此;
当待排记录序列按关键字顺序有序时,直接插入排序和起泡排序能达到O(n)的时间复杂度;而对于快速排序而言,这是最不好的情况,此时的时间性能蜕化为O(n2),因此是应该尽量避免的情况。简单选择排序、堆排序和归并排序的时间性能不随记录序列中关键字的分布而改变。
——按平均的空间性能来分(指的是排序过程中所需的辅助空间大小):
1) 所有的简单排序方法(包括:直接插入、起泡和简单选择)和堆排序的空间复杂度为O(1);
2) 快速排序为O(logn ),为栈所需的辅助空间;
3) 归并排序所需辅助空间最多,其空间复杂度为O(n );
4)链式基数排序需附设队列首尾指针,则空间复杂度为O(rd )。
——排序方法的稳定性能:
1) 稳定的排序方法指的是,对于两个关键字相等的记录,它们在序列中的相对位置,在排序之前和 经过排序之后,没有改变。
2) 当对多关键字的记录序列进行LSD方法排序时,必须采用稳定的排序方法。
3) 对于不稳定的排序方法,只要能举出一个实例说明即可。
4) 快速排序,希尔排序和堆排序是不稳定的排序方法。
所需辅助空间最多:归并排序
所需辅助空间最少:堆排序
平均速度最快:快速排序
不稳定:快速排序,希尔排序,堆排序。
=================================================================
4.结合堆排序,分析最大(小)堆建立、插入、删除的时间复杂度
最大堆就是:所有的父亲都比儿子要大,且是完全(完全不一定满)二叉树
buildHeap:O(n)注意是不是O(logn):从最后一个元素/2开始(减1循环),percolateDown.见数据结构试卷P14页背面
DeleteMin: O(logn):把堆顶元素和最后一个元素B交换,让B从堆顶percolateDown.英文数据结构P152
Insert:O(logn):插入称为最后一个叶节点,然后向上回溯找到位置
===================================
二叉搜素树:
什么是搜素二叉树。任何一个结点的左边子节点所有的孙结点都小于它,右边的都大于它P27
查找x:O(d) d是depth是树的深度。从顶结点开始,如果结点小于x,则往左边找,结点大于x,则往右边找,结点等于x,则返回。英文数据结构P99
查找最小值:O(d)一直往左边找 英文数据结构P99
查找最大值:O(d)一直往右边找 英文数据结构P100
插入:O(d)从顶上结点开始比较往下顺,如果找到位置,插入.英文数据结构P101
删除: O(d)英文数据结构P102
(1)如果删除的是叶节点,则直接删除,把它父节点->next设为null
(2)如果删除的结点只有一个child a,则把a父节点->next设为a的儿子,a 删掉
(3)如果删除的结点有两个child,则用右子树的最小值取代这个值(或者左子树的最大值),然后右子树删掉那个最小值(或者左子树删掉那个最大值)
===================================================
AVL Trees:
definition(英文数据结构P106):,每个结点的左子树和右子树的高度最大相差1的二叉搜索树
target:加快搜素(插入、删除)
======================================================
拓扑排序:;例子有一些课程是在一些课程之后才能学的,叫你给出一个学习的顺序。拓扑排序不能有环 数据结构课件DS10_Ch09b.pps
O(|V|+|E|)
======================================================
Dijkstra算法:O|V|.单源最短路径问题(其它所有点与一个开始点间的最短路径)
看算法导论P367的图即可明白
Dijkstra是贪心算法,因为每次选择时,都是选择最小值的结点开始访问
Dijkstra是广度优先搜索的类似例子,因为每次访问一个对象,被它指向的对象都会修改值,而且选择最小的边。因为未访问的都设置为无穷,所以实际上也是广度优先搜索(看不懂就算了)
伪代码看白纸笔记P4和P6
======================================================
Kruskal算法:用来生成图的最小生成树(边值和最小)O(|E|log|E|)看算法导论P349的图即可明白
也是贪心算法,每次都是查看最小的边,有环则放弃,没环就打上
伪代码看算法导论P348
Prim算法:用来生成图的最小生成树, 看算法导论P350的图即可明白
也是贪心算法,类似于Dijkstra,从一个点出发,只有一个树,每次找这棵树之外的最小的边加入到这棵树中
Prim算法是广度优先搜索的例子,因为每次找这棵树之外的最小的边加入到这棵树中就是广度优先搜索
=======================================================
红黑树:算法导论P163 target:加快搜素(插入、删除)
红黑树是一种平衡的二叉查找树,每个结点着色(Red或者black),通过对着色方式的限制(对于每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点),红黑树确保没有一条路径比其它路径长出两倍,因而是接近平衡的。正因为平衡,红黑树保证在最坏情况下,基本操作也达到O(lgn).因为一般高度为h的二叉树的操作时间都是O(h),即红黑树保证h不会过大,是lgn的。
红黑性质:
每个结点或是红的,或是黑的
根结点是黑的
每个叶节点(nil)是黑的
如果一个结点是红的,则它的两个儿子都是黑的
对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。
红黑树的插入操作:通过重新着色,左旋和右旋(了解一下)
======================================================
======================================================
题目:google : programming interview question, algorithm interview question
1.查找两个已经排好序的数组的第k大的元素(中位数是此题的特殊情况(sa+sb)/2)
median of two sorted array
数组a,大小sa;数组b,大小sb
要求时间复杂度是O(log(sa+sb))
最直接的想法是类似于归并算法,两个游标,一个游a,一个游b,时间复杂度O(sa+sb)
第2种解法,有点而类似二分查找O(log(sa+sb))。附见笔记1,参考http://www.amirwatad.com/blog/archives/2010/03/06/finding-the-median-of-two-sorted-arrays/
------------------------------------------------------
2.二叉树先序遍历和中序遍历的非递归实现
用stack就可以,可以参照http://www.iteye.com/topic/507806
先循环把左节点加入栈,如果栈里还有元素的话,把栈里的顶元素取出来,访问它的右节点
先序遍历和中序遍历差不多,就是打印的句子出现的位置不一样。
其实后序遍历也差不多
------------------------------------------------------
3.查找两个字符串的最长公共子字符串(LCS--longest common substring)
参考:http://en.wikipedia.org/wiki/Longest_common_substring_problem#Suffix_tree
1.动态规划法(看上面的链接很容易明白,O(mn),m,n为两个字符串的长度): 思想,从小到大,find the longest common suffix for all pairs of prefixes of the strings.(查找所有的前缀子字符串的公共后缀字符串)
2.还有一个后缀树的方法,据说复杂度是O(m+n),待
查找两个字符串的最长公共子序列(LCS---longest common subsequence)和最长公共子字符串不同的是子序列不要求是连续的
DP:(1) 当X[i]=Y[j]时, L(i, j)=L(i-1, j-1)+1 。证明很简单。
(2) 当X[i]!=Y[j]时, 说明此事X[0...i]和Y[0...j]的最长公共子序列中绝对不可能同时含有X[i]和Y[j]。那么公共子序列可能以X[i]结尾,可能以Y[j]结尾,可以末尾都不含有X[i]或Y[j]。因此
L(i, j)= MAX{L(i-1 , j), L(i, j-1)}
很简单见链接http://hxraid.iteye.com/blog/622462
-------------------------------------------------------
4.查找一个字符串的最长回文子串------------------------------------------------------
5.判断链表是否有环(Find if a linked list has a cycle in it.)
O(n)
一个快指针(两倍速度),一个慢指针(一倍速度)
下面这个链接的底部
http://ostermiller.org/find_loop_singly_linked_list.html
-------------------------------------------------------
6.把一个字符串的单词反过来,是就地反Reverse Words In a String
O(n)
反转单词,如"hello my world ”--->"world my hello"空格有时候不止一个
void ReverseWordsInString(char *str)
{
int start, end, length;
length=strlen(str);
ReverseString(str, 0, length-1);//首先是整个反转
start=end=0;
while (end < length)
{
if (str[end] ! = ' ')//一个单词的开始
{
start=end;
while (str[end] != ' ' && end < length)//找到单词的介绍
end++;
end--;
ReverseString(str, start, end);//反转这个单词
}
end++;
}
}
//反转字符串(注意不是反转单词),即第1个和最后一个互换,第2个和倒数第2个互换
void ReverseString(str, start, end)
{
char *temp;
while (start < end)
{
temp=str[start];
str[start]=str[end];
str[end]=temp;
start++;
end--;
}
}
----------------------------------------------
7.查找字符串中第一个不重复的字符:Find the first non-repeating character in a string
方法Hash,两次遍历。第一次遍历是计算频率,第二次遍历是从左到右查看频率为1的字符
参考http://geeksforgeeks.org/?p=1781
-----------------------------------------------
8.查找第k-th smallest element in 二叉查找树O(lgn)
Finding kth smallest element in Binary Tree
递归查找即可
http://mukeshiiitm.wordpress.com/2010/04/07/finding-kth-smallest-element-in-binary/
-----------------------------------------------
9.在数组中查找第k小的元素
可以建立一个k大小的最大堆O(k),如果比堆顶小,就insert到堆中O(lgk),因此时间复杂度是O(k+nlogk)-->O(nlogk),节约空间
可以用快排Parition(O(n))的思想,虽然快排时间复杂度是O(nlgn),但是仅是查找第k个元素的话时间复杂度仅是O(nlgk),但是可能就改变了数组的元素顺序了
快排partition的过程可以参考算法导论P85-86看程序再看图即可明白
而查找第k个元素的话,可以比较k和pivotIndex的大小,再决定往左边还是右边继续跑
程序参考http://en.wikipedia.org/wiki/Selection_algorithm
//和算法导论的差不多,看算法导论的
function partition(list, left, right, pivotIndex)
pivotValue := list[pivotIndex]
swap list[pivotIndex] and list[right] // Move pivot to end
storeIndex := left
for i from left to right-1
if list[i] < pivotValue
swap list[storeIndex] and list[i]
storeIndex := storeIndex + 1
swap list[right] and list[storeIndex] // Move pivot to its final place
return storeIndex
//注意,最后一行它写错了
function select(list, left, right, k)
select pivotIndex between left and right
pivotNewIndex := partition(list, left, right, pivotIndex)
if k = pivotNewIndex
return list[k]
else if k < pivotNewIndex
return select(list, left, pivotNewIndex-1, k)
else
return select(list, pivotNewIndex+1, right, k-pivotNewIndex)
扩展问题
(1)查找前k个数,partition中最后找到排序第k个序号前面的都是
堆排序中前k个数就是堆中的元素了
(2)第k到m大的数(比如第500到600的数),方法是一个500的最大堆找到第500小的元素,然后一个以第500小的元素做判断(大于这个元素才加进堆里面)的堆大小为600-500的最小堆,时间复杂度应该是O(nlgk+nlg(m-k))
如果n很大的话就用堆排序,不用快排的partition思想
-------------------------------------------------
可以花半天时间看一下编程之美的这些题
10.求二进制数中1的个数(编程之美---P119)
解法2 while(v){num+=v&0x01; v>>=1} 时间复杂度O(logv)
解法3 巧妙的解法 while(v){v &= (v-1); num++} 时间复杂度O(v中1的个数)
解法4 先存好256个数的1的个数,然后再访问,汗。。。 空间复杂度换时间复杂度,O(1)
扩展问题:A变成B需要改变多少位(bit),也就是A和B的二进制表示中有多少位是不同的?
C=A和B异或,再求C二进制中1的个数
--------------------------------------------------
11.阶乘(编程之美---P125)基本问题:N!有质因数m的个数
ret = 0;
while(N){
N /= m;
ret += N;
}
问题1,N!的末尾有多少个0,如N=10, N!=3628800, 末尾有两个0
问题1转化为基本问题,N!有质因数5的个数(至于怎样转化看编程之美)
问题2,求N!的二进制表示中最低位1的位置
问题2转化为基本问题,N!有质因数2的个数(至于怎样转化看编程之美)
扩展问题:判断整数n是否是2的方幂
思想,2的方幂是二进制表示中只有1个1,其它都为0,因此 (n>0 && (n & (n-1))==0)有点类似于上面那题解法3
-------------------------------------------------
12.最大公约数 (编程之美P151)解法2
f(42,30) = f(30,12)=f(18,12) = f(12,6) =f(6,0)=6
gcd(x,y){
if(x<y) return gcd(y,x);
if(y == 0) return x;
else return gcd(x-y, y);
}
-------------------------------------------------
13.寻找数组中的最大值和最小值的比较次数(编程之美P165)一边扫描,记录,需要比较2N次,max比较N次,min比较N次
解法2,1.5*N次,它是先以2大小为一单元切割,单元中大的排在前头,小的排在后面(N/2的比较次数),然后比较偶数位的需要N/2的比较找到最大,比较奇数位的需要N/2的比较找到最小,因此需要N/2+N/2+N/2 = 1.5N次比较
1.5N次比较式最小的了
可以看看解法4,看看分治思想
--------------------------------------------------
14.找数组中满足a+b = sum(sum为给定的一个数)的a和b,
思想:
解法2:先排序O(NlgN),对每个元素a,计算出sum-a,二分查找看sum-a在不在数组中O(lgN),每个元素都要计算,就是O(N*lgN),
总的O(NlgN+NlgN) = O(NlgN)
解法三,先排序O(NlgN),
第一个元素和最后一个元素相加和sum比较,如果>sum,则第一个元素后移,<sum,最后一个元素前移, = sum返回 O(N)
总的复杂度为O(NlgN+N)=O(NlgN)
空间换取时间的解法
每个元素hash存一下O(N)
对于每个元素a,计算sum-a在不在hash表中 O(1) ,N个元素O(N*1)
O(N)+O(N*1) = O(N)
但是空间上多了O(N)的hash表
------------------------------------------------
15.求数组中的最长递归子序列(编程之美P194)1, -1, 2 , -3, 1000, 4, -5, 6, -7
得到
-1, 2, 4, 6
编程之美的解析不是太好,可以边参考编程之美,边参考以下url
http://student.csdn.net/space.php?uid=116484&do=blog&id=39673
初始想法dp:每个以一个字符结束的最长递归子序列的长度是多少,然后遍历比较,见解法1
时间复杂度O(N^2)
优化:记录minV(最长递归子序列长度)优化的见编程之美(见上面URL和我写在旁边的附注)
时间复杂度O(NlgN)?(试)
-------------------------------------------------
16.字符串移位包含 (编程之美P215)看解法二,双倍连接原字符串,再查看是不是包括小的即可
-------------------------------------------------
17.数组循环移位(编程之美P199)看最后的解法2,easy。和反转单词差不多,见上面6
------------------------------------------------
18.从无头单链表中删除节点(编程之美P226)因为链表无头,所以不能从头遍历
只能内容替换
看书即可,很快明白
-------------------------------------------------
19.判断两个链表是否相交P235首先要明白什么是相交链表,就是前面是分开的,后面是重叠的,一直重叠到底
解法2,hash的方法,首先hash第一个链表的地址,再遍历第二个链表的地址,看是否在hash表中,时间复杂度O(len(h1)+len(h2)),但是建hash表有额外空间消耗O(len(h1))
解法3,转为判断链表是否有环的问题,见上面5,把第1个链表的尾节点连接第2个链表的头节点,遍历第2个链表,看是否有环(这有个前提,就是一开始给的两个链表无环)
最好的方法解法四,看两个链表的最后一个节点是否相同,即可O(len(h1)+len(h2))
扩展问题:
1.怎样求出两个链表相交的第一个结点,
遍历第一个链表,得到长度len(h1),遍历第二个链表,得到长度len(h2)
看看那个长,再长的链表提前|len(h1)-len(h2)|步开始走,然后比较,直到相等的,即为第一个相交结点。
2.如果链表有环,怎样判断两个链表是否相交
判断第1个链表是否有环,用一快一慢指针,得到一个在环内的结点A(快慢指针重叠的位置)
判断第2个链表是否有环,用一快一慢指针,如果无环--->不相交,如果有环,在得到有(快慢指针重叠的位置还没发现第一个链表的a的话--->不想交,发现--->相交
---------------------------------------------------
19-1:给一个字符串和一个字符集,求该字符串包含字符集的最短子串http://club.itqun.net/showtopic-207005.html
就是给一个很长的字符串str 还有一个字符集比如{a,b,c} 找出str里包含{a,b,c}的最短子串。要求O(n)?
比如,字符集是a,b,c,字符串是abdcaabcx,则最短子串为abc
用两个变量 front rear 指向一个的子串区间的头和尾
用一个int cnt[255]={0}记录当前这个子串里 字符集a,b,c 各自的个数,一个变量sum记录字符集里有多少个了
rear 一直加,更新cnt[]和sum的值,直到 sum等于字符集个数
然后front++,直到cnt[]里某个字符个数为0,这样就找到一个符合条件的字串了
继续前面的操作,就可以找到最短的了
---------------------------------------------------
19-2:5个数排序 要比较的最少次数
7次http://blog.csdn.net/fisher_jiang/archive/2008/05/13/2442486.aspx
---------------------------------------------------
20.Lowest Common Ancestor(待)http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor
---------------------------------------------------
20.背包问题与最小数目硬币(dynamic programming)最小数目硬币,给出一个sum比如11,给出有几种硬币,比如1,3,5,求用最少的硬币数达到sum,这里为551,三枚。见http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg
看看代码很容易明白。sum从1开始遍历,小于sum的都已经计算过了,则遍历一下所有的硬币,如果vj<sum则加进来,sum-vj已经求过了
Set Min[i] equal to Infinity for all of i
Min[0]=0
For i = 1 to S
For j = 0 to N - 1
If (Vj<=i AND Min[i-Vj]+1<Min[i])
Then Min[i]=Min[i-Vj]+1
Output Min[S]
背包问题:见
http://xmuzzx.blog.hexun.com/39126356_d.html
即,看url那个图,即从上到下一项项物品往下遍历
f(i,j)遍历到第i项物品,j为背包的价值容量
if(w[n]<m)
//不把n加进来,和把n加进来取一个最大值,所有的f(n-1,m)的值已经先前计算出来了
f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n)}//p(n)为第n项物品的价值
else
f(n,m)=f(n-1,m)
----------------------------------------
21 从两个文件(各含50亿个url)中找出共同的url
http://mianshiti.blog.sohu.com/144535301.html
可以估计每个文件的大小为5G*64=300G,远大于4G。所以不可能将其完全加载到内存中处理。考虑采取分而治之的方法。
遍历文件a,对每个url求取hash(url)%1000,然后根据所得值将url分别存储到1000个小文件(设为 a0,a1,...a999)当中。这样每个小文件的大小约为300M。遍历文件b,采取和a相同的方法将url分别存储到1000个小文件 (b0,b1....b999)中。这样处理后,所有可能相同的url都在对应的小文件(a0 vs b0, a1 vs b1....a999 vs b999)当中,不对应的小文件(比如a0 vs b99)不可能有相同的url。然后我们只要求出1000对小文件中相同的url即可。
比如对于a0 vs b0,我们可以遍历a0,将其中的url存储到hash_map当中。然后遍历b0,如果url在hash_map中,则说明此url在a和b中同时存在,保存到文件中即可。
如果分成的小文件不均匀,导致有些小文件太大(比如大于2G),可以考虑将这些太大的小文件再按类似的方法分成小小文件即可。
---------------------------------------------
22.有1到10w这10w个数,去除2个并打乱次序,如何找出那两个数?
方法一:
申请10w个bit的空间,每个bit代表一个数字是否出现过。
开始时将这10w个bit都初始化为0,表示所有数字都没有出现过。
然后依次读入已经打乱循序的数字,并将对应的bit设为1。
当处理完所有数字后,根据为0的bit得出没有出现的数字。
方法二:
首先计算1到10w的和,平方和。
然后计算给定数字的和,平方和。
两次的到的数字相减,可以得到这两个数字的和,平方和。
所以我们有
x + y = n
x^2 + y^2 = m
解方程可以得到x和y的值。
---------------------------------------------
23.如何找出字典中的兄弟单词http://mianshiti.blog.sohu.com/144535354.html
问题:
给定一个单词a,如果通过交换单词中字母的顺序可以得到另外的单词b,那么定义b是a的兄弟单词。现在给定一个字典,用户输入一个单词,如何根据字典找出这个单词有多少个兄弟单词?
答案:
使用hash_map和链表。
首先定义一个key,使得兄弟单词有相同的key,不是兄弟的单词有不同的key。例如,将单词按字母从小到大重新排序后作为其key,比如bad的key为abd,good的key为dgoo。
使用链表将所有兄弟单词串在一起,hash_map的key为单词的key,value为链表的起始地址。
开始时,先遍历字典,将每个单词都按照key加入到对应的链表当中。当需要找兄弟单词时,只需求取这个单词的key,然后到hash_map中找到对应的链表即可。
这样创建hash_map时时间复杂度为O(n),查找兄弟单词时时间复杂度是O(1)。
-------------------------------------------
24.海量日志数据,提取出某日访问百度次数最多的那个IP。
IP地址最多有2^32=4G种取值可能,所以不能完全加载到内存中。
可以考虑分而治之的策略,按照IP地址的hash(IP)%1024值,将海量日志存储到1024个小文件中。每个小文件最多包含4M个IP地址。
对于每个小文件,可以构建一个IP作为key,出现次数作为value的hash_map,并记录当前出现次数最多的1个IP地址。
有了1024个小文件中的出现次数最多的IP,我们就可以轻松得到总体上出现次数最多的IP。
----------------------------------------------------
atoi:
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <ctype.h>
4
5 long my_atol(const char *nptr)
6 {
7 int c; /* current char */
8 long total; /* current total */
9 int sign; /* if '-', then negative, otherwise positive */
10
11 /* skip whitespace */
12 while ( isspace((int)(unsigned char)*nptr) )
13 {
14 ++nptr;
15 }
16
17 c = (int)(unsigned char)*nptr++;
18 sign = c; /* save sign indication */
19 if (c == '-' || c == '+')
20 {
21 c = (int)(unsigned char)*nptr++; /* skip sign */
22 }
23
24 total = 0;
25
26 while (isdigit(c))
27 {
28 total = 10 * total + (c - '0'); /* accumulate digit */
29 c = (int)(unsigned char)*nptr++; /* get next char */
30 }
31
32 if (sign == '-')
33 {
34 return -total;
35 }
36 else
37 {
38 return total; /* return result, negated if necessary */
39 }
40 }
strcmp:
int strcmp(const char *src,const char *dst)
{
int ret=0;
while(!(ret=*(unsigned char *)src-*(unsigned char *)dst) && *dst)
++src,++dst;
if(ret<0)
ret=-1;
else if(ret>0)
ret=1;
return ret;
}
memcpy:
void* memcpy( void* dest, const void* src, size_t count )
{
if (count<0){
printf("Invalid count number !.\n");
return (void*)0;
}
if(src==NULL||dest==NULL)
return (void*)0 ;
if ((unsigned int)dest==(unsigned int)src){
printf("The source is equal with the destanation!.\n");
return dest;
}
char* d = (char*)dest;
const char* s = (const char*)src;
while(count--)
*d++ = *s++;
return dest;
}
quickSort:
前序遍历(非递归实现):
中序遍历非递归实现(和上面差不多,访问的位置不同):
注意时间复杂度
1.给出一个数列,找出连续相加最大的和
方法:(1)O(n) 一次扫描,如果sum<0, sum = 0. 英文数据结构书p23
(2)O(nlogn) devide and conqure 左右两边分别找最大,合并后的值,看看最后左、右、合并三个哪个最大 英文数据结构书p21
=================================================================
2.二分查找 O(logN)整个数列已经之前排过序才能二分查找。每次比较选中间这个,如果比中间这个大,则继续找右边的中间值,否则找左边. 英文数据结构书p23
=================================================================
3.各种排序算法
参考java各种排序算法http://shulin-success.iteye.com/blog/493705其中讲到各种排序算法的时间复杂度和空间复杂度。
这个也有用排序算法http://hzhping350.blog.163.com/blog/static/831207362008821102419976/
1.冒泡排序:程序见算法导论 P23底 思想:最小的先冒起来
2.插入排序:思想:就像我们抓牌,插牌一样.在数列大部分有序的情况下比快排有效。最好情况O(n)
3.希尔排序: 思想见:数据结构课件DS07_Ch06a.pps第5页
4.堆排序:把数字填入初始化堆(未排序,只是按顺序填入)-->然后调整为最小堆(或最大堆)buildHeap--->然后排序 见数据结构试卷P14页背面教你怎样buildHeap.数据结构试卷P7及背面教你怎样heapSort
5.归并排序
6.快速排序:思想:找到一个pivot,把原数据集分为两个子集,一个大于pivot,一个小于pivot。pivot的位置就定了,在小于集(pivot)大于集.
7.桶排序:把区间[0,1)划分为n个相同大小的子区间(即桶),先对各个桶中的数进行排序,然后按桶的次序列出数字即可。需额外空间O(n),在数符合均匀分布的情况下,O(n)
3)总结:
——按平均的时间性能来分:
1)时间复杂度为O(nlogn)的方法有:快速排序、堆排序和归并排序,其中以快速排序为最好;
2)时间复杂度为O(n2)的有:直接插入排序、起泡排序和简单选择排序,其中以直接插入为最好,特 别是对那些对关键字近似有序的记录序列尤为如此;
当待排记录序列按关键字顺序有序时,直接插入排序和起泡排序能达到O(n)的时间复杂度;而对于快速排序而言,这是最不好的情况,此时的时间性能蜕化为O(n2),因此是应该尽量避免的情况。简单选择排序、堆排序和归并排序的时间性能不随记录序列中关键字的分布而改变。
——按平均的空间性能来分(指的是排序过程中所需的辅助空间大小):
1) 所有的简单排序方法(包括:直接插入、起泡和简单选择)和堆排序的空间复杂度为O(1);
2) 快速排序为O(logn ),为栈所需的辅助空间;
3) 归并排序所需辅助空间最多,其空间复杂度为O(n );
4)链式基数排序需附设队列首尾指针,则空间复杂度为O(rd )。
——排序方法的稳定性能:
1) 稳定的排序方法指的是,对于两个关键字相等的记录,它们在序列中的相对位置,在排序之前和 经过排序之后,没有改变。
2) 当对多关键字的记录序列进行LSD方法排序时,必须采用稳定的排序方法。
3) 对于不稳定的排序方法,只要能举出一个实例说明即可。
4) 快速排序,希尔排序和堆排序是不稳定的排序方法。
所需辅助空间最多:归并排序
所需辅助空间最少:堆排序
平均速度最快:快速排序
不稳定:快速排序,希尔排序,堆排序。
=================================================================
4.结合堆排序,分析最大(小)堆建立、插入、删除的时间复杂度
最大堆就是:所有的父亲都比儿子要大,且是完全(完全不一定满)二叉树
buildHeap:O(n)注意是不是O(logn):从最后一个元素/2开始(减1循环),percolateDown.见数据结构试卷P14页背面
DeleteMin: O(logn):把堆顶元素和最后一个元素B交换,让B从堆顶percolateDown.英文数据结构P152
Insert:O(logn):插入称为最后一个叶节点,然后向上回溯找到位置
===================================
二叉搜素树:
什么是搜素二叉树。任何一个结点的左边子节点所有的孙结点都小于它,右边的都大于它P27
查找x:O(d) d是depth是树的深度。从顶结点开始,如果结点小于x,则往左边找,结点大于x,则往右边找,结点等于x,则返回。英文数据结构P99
查找最小值:O(d)一直往左边找 英文数据结构P99
查找最大值:O(d)一直往右边找 英文数据结构P100
插入:O(d)从顶上结点开始比较往下顺,如果找到位置,插入.英文数据结构P101
删除: O(d)英文数据结构P102
(1)如果删除的是叶节点,则直接删除,把它父节点->next设为null
(2)如果删除的结点只有一个child a,则把a父节点->next设为a的儿子,a 删掉
(3)如果删除的结点有两个child,则用右子树的最小值取代这个值(或者左子树的最大值),然后右子树删掉那个最小值(或者左子树删掉那个最大值)
===================================================
AVL Trees:
definition(英文数据结构P106):,每个结点的左子树和右子树的高度最大相差1的二叉搜索树
target:加快搜素(插入、删除)
======================================================
拓扑排序:;例子有一些课程是在一些课程之后才能学的,叫你给出一个学习的顺序。拓扑排序不能有环 数据结构课件DS10_Ch09b.pps
O(|V|+|E|)
======================================================
Dijkstra算法:O|V|.单源最短路径问题(其它所有点与一个开始点间的最短路径)
看算法导论P367的图即可明白
Dijkstra是贪心算法,因为每次选择时,都是选择最小值的结点开始访问
Dijkstra是广度优先搜索的类似例子,因为每次访问一个对象,被它指向的对象都会修改值,而且选择最小的边。因为未访问的都设置为无穷,所以实际上也是广度优先搜索(看不懂就算了)
伪代码看白纸笔记P4和P6
======================================================
Kruskal算法:用来生成图的最小生成树(边值和最小)O(|E|log|E|)看算法导论P349的图即可明白
也是贪心算法,每次都是查看最小的边,有环则放弃,没环就打上
伪代码看算法导论P348
Prim算法:用来生成图的最小生成树, 看算法导论P350的图即可明白
也是贪心算法,类似于Dijkstra,从一个点出发,只有一个树,每次找这棵树之外的最小的边加入到这棵树中
Prim算法是广度优先搜索的例子,因为每次找这棵树之外的最小的边加入到这棵树中就是广度优先搜索
=======================================================
红黑树:算法导论P163 target:加快搜素(插入、删除)
红黑树是一种平衡的二叉查找树,每个结点着色(Red或者black),通过对着色方式的限制(对于每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点),红黑树确保没有一条路径比其它路径长出两倍,因而是接近平衡的。正因为平衡,红黑树保证在最坏情况下,基本操作也达到O(lgn).因为一般高度为h的二叉树的操作时间都是O(h),即红黑树保证h不会过大,是lgn的。
红黑性质:
每个结点或是红的,或是黑的
根结点是黑的
每个叶节点(nil)是黑的
如果一个结点是红的,则它的两个儿子都是黑的
对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。
红黑树的插入操作:通过重新着色,左旋和右旋(了解一下)
======================================================
======================================================
题目:google : programming interview question, algorithm interview question
1.查找两个已经排好序的数组的第k大的元素(中位数是此题的特殊情况(sa+sb)/2)
median of two sorted array
数组a,大小sa;数组b,大小sb
要求时间复杂度是O(log(sa+sb))
最直接的想法是类似于归并算法,两个游标,一个游a,一个游b,时间复杂度O(sa+sb)
第2种解法,有点而类似二分查找O(log(sa+sb))。附见笔记1,参考http://www.amirwatad.com/blog/archives/2010/03/06/finding-the-median-of-two-sorted-arrays/
------------------------------------------------------
2.二叉树先序遍历和中序遍历的非递归实现
用stack就可以,可以参照http://www.iteye.com/topic/507806
先循环把左节点加入栈,如果栈里还有元素的话,把栈里的顶元素取出来,访问它的右节点
先序遍历和中序遍历差不多,就是打印的句子出现的位置不一样。
其实后序遍历也差不多
------------------------------------------------------
3.查找两个字符串的最长公共子字符串(LCS--longest common substring)
参考:http://en.wikipedia.org/wiki/Longest_common_substring_problem#Suffix_tree
1.动态规划法(看上面的链接很容易明白,O(mn),m,n为两个字符串的长度): 思想,从小到大,find the longest common suffix for all pairs of prefixes of the strings.(查找所有的前缀子字符串的公共后缀字符串)
2.还有一个后缀树的方法,据说复杂度是O(m+n),待
查找两个字符串的最长公共子序列(LCS---longest common subsequence)和最长公共子字符串不同的是子序列不要求是连续的
DP:(1) 当X[i]=Y[j]时, L(i, j)=L(i-1, j-1)+1 。证明很简单。
(2) 当X[i]!=Y[j]时, 说明此事X[0...i]和Y[0...j]的最长公共子序列中绝对不可能同时含有X[i]和Y[j]。那么公共子序列可能以X[i]结尾,可能以Y[j]结尾,可以末尾都不含有X[i]或Y[j]。因此
L(i, j)= MAX{L(i-1 , j), L(i, j-1)}
很简单见链接http://hxraid.iteye.com/blog/622462
-------------------------------------------------------
4.查找一个字符串的最长回文子串------------------------------------------------------
5.判断链表是否有环(Find if a linked list has a cycle in it.)
O(n)
一个快指针(两倍速度),一个慢指针(一倍速度)
下面这个链接的底部
http://ostermiller.org/find_loop_singly_linked_list.html
-------------------------------------------------------
6.把一个字符串的单词反过来,是就地反Reverse Words In a String
O(n)
反转单词,如"hello my world ”--->"world my hello"空格有时候不止一个
void ReverseWordsInString(char *str)
{
int start, end, length;
length=strlen(str);
ReverseString(str, 0, length-1);//首先是整个反转
start=end=0;
while (end < length)
{
if (str[end] ! = ' ')//一个单词的开始
{
start=end;
while (str[end] != ' ' && end < length)//找到单词的介绍
end++;
end--;
ReverseString(str, start, end);//反转这个单词
}
end++;
}
}
//反转字符串(注意不是反转单词),即第1个和最后一个互换,第2个和倒数第2个互换
void ReverseString(str, start, end)
{
char *temp;
while (start < end)
{
temp=str[start];
str[start]=str[end];
str[end]=temp;
start++;
end--;
}
}
----------------------------------------------
7.查找字符串中第一个不重复的字符:Find the first non-repeating character in a string
方法Hash,两次遍历。第一次遍历是计算频率,第二次遍历是从左到右查看频率为1的字符
参考http://geeksforgeeks.org/?p=1781
-----------------------------------------------
8.查找第k-th smallest element in 二叉查找树O(lgn)
Finding kth smallest element in Binary Tree
递归查找即可
http://mukeshiiitm.wordpress.com/2010/04/07/finding-kth-smallest-element-in-binary/
-----------------------------------------------
9.在数组中查找第k小的元素
可以建立一个k大小的最大堆O(k),如果比堆顶小,就insert到堆中O(lgk),因此时间复杂度是O(k+nlogk)-->O(nlogk),节约空间
可以用快排Parition(O(n))的思想,虽然快排时间复杂度是O(nlgn),但是仅是查找第k个元素的话时间复杂度仅是O(nlgk),但是可能就改变了数组的元素顺序了
快排partition的过程可以参考算法导论P85-86看程序再看图即可明白
而查找第k个元素的话,可以比较k和pivotIndex的大小,再决定往左边还是右边继续跑
程序参考http://en.wikipedia.org/wiki/Selection_algorithm
//和算法导论的差不多,看算法导论的
function partition(list, left, right, pivotIndex)
pivotValue := list[pivotIndex]
swap list[pivotIndex] and list[right] // Move pivot to end
storeIndex := left
for i from left to right-1
if list[i] < pivotValue
swap list[storeIndex] and list[i]
storeIndex := storeIndex + 1
swap list[right] and list[storeIndex] // Move pivot to its final place
return storeIndex
//注意,最后一行它写错了
function select(list, left, right, k)
select pivotIndex between left and right
pivotNewIndex := partition(list, left, right, pivotIndex)
if k = pivotNewIndex
return list[k]
else if k < pivotNewIndex
return select(list, left, pivotNewIndex-1, k)
else
return select(list, pivotNewIndex+1, right, k-pivotNewIndex)
扩展问题
(1)查找前k个数,partition中最后找到排序第k个序号前面的都是
堆排序中前k个数就是堆中的元素了
(2)第k到m大的数(比如第500到600的数),方法是一个500的最大堆找到第500小的元素,然后一个以第500小的元素做判断(大于这个元素才加进堆里面)的堆大小为600-500的最小堆,时间复杂度应该是O(nlgk+nlg(m-k))
如果n很大的话就用堆排序,不用快排的partition思想
-------------------------------------------------
可以花半天时间看一下编程之美的这些题
10.求二进制数中1的个数(编程之美---P119)
解法2 while(v){num+=v&0x01; v>>=1} 时间复杂度O(logv)
解法3 巧妙的解法 while(v){v &= (v-1); num++} 时间复杂度O(v中1的个数)
解法4 先存好256个数的1的个数,然后再访问,汗。。。 空间复杂度换时间复杂度,O(1)
扩展问题:A变成B需要改变多少位(bit),也就是A和B的二进制表示中有多少位是不同的?
C=A和B异或,再求C二进制中1的个数
--------------------------------------------------
11.阶乘(编程之美---P125)基本问题:N!有质因数m的个数
ret = 0;
while(N){
N /= m;
ret += N;
}
问题1,N!的末尾有多少个0,如N=10, N!=3628800, 末尾有两个0
问题1转化为基本问题,N!有质因数5的个数(至于怎样转化看编程之美)
问题2,求N!的二进制表示中最低位1的位置
问题2转化为基本问题,N!有质因数2的个数(至于怎样转化看编程之美)
扩展问题:判断整数n是否是2的方幂
思想,2的方幂是二进制表示中只有1个1,其它都为0,因此 (n>0 && (n & (n-1))==0)有点类似于上面那题解法3
-------------------------------------------------
12.最大公约数 (编程之美P151)解法2
f(42,30) = f(30,12)=f(18,12) = f(12,6) =f(6,0)=6
gcd(x,y){
if(x<y) return gcd(y,x);
if(y == 0) return x;
else return gcd(x-y, y);
}
-------------------------------------------------
13.寻找数组中的最大值和最小值的比较次数(编程之美P165)一边扫描,记录,需要比较2N次,max比较N次,min比较N次
解法2,1.5*N次,它是先以2大小为一单元切割,单元中大的排在前头,小的排在后面(N/2的比较次数),然后比较偶数位的需要N/2的比较找到最大,比较奇数位的需要N/2的比较找到最小,因此需要N/2+N/2+N/2 = 1.5N次比较
1.5N次比较式最小的了
可以看看解法4,看看分治思想
--------------------------------------------------
14.找数组中满足a+b = sum(sum为给定的一个数)的a和b,
思想:
解法2:先排序O(NlgN),对每个元素a,计算出sum-a,二分查找看sum-a在不在数组中O(lgN),每个元素都要计算,就是O(N*lgN),
总的O(NlgN+NlgN) = O(NlgN)
解法三,先排序O(NlgN),
第一个元素和最后一个元素相加和sum比较,如果>sum,则第一个元素后移,<sum,最后一个元素前移, = sum返回 O(N)
总的复杂度为O(NlgN+N)=O(NlgN)
空间换取时间的解法
每个元素hash存一下O(N)
对于每个元素a,计算sum-a在不在hash表中 O(1) ,N个元素O(N*1)
O(N)+O(N*1) = O(N)
但是空间上多了O(N)的hash表
------------------------------------------------
15.求数组中的最长递归子序列(编程之美P194)1, -1, 2 , -3, 1000, 4, -5, 6, -7
得到
-1, 2, 4, 6
编程之美的解析不是太好,可以边参考编程之美,边参考以下url
http://student.csdn.net/space.php?uid=116484&do=blog&id=39673
初始想法dp:每个以一个字符结束的最长递归子序列的长度是多少,然后遍历比较,见解法1
时间复杂度O(N^2)
优化:记录minV(最长递归子序列长度)优化的见编程之美(见上面URL和我写在旁边的附注)
时间复杂度O(NlgN)?(试)
-------------------------------------------------
16.字符串移位包含 (编程之美P215)看解法二,双倍连接原字符串,再查看是不是包括小的即可
-------------------------------------------------
17.数组循环移位(编程之美P199)看最后的解法2,easy。和反转单词差不多,见上面6
------------------------------------------------
18.从无头单链表中删除节点(编程之美P226)因为链表无头,所以不能从头遍历
只能内容替换
看书即可,很快明白
-------------------------------------------------
19.判断两个链表是否相交P235首先要明白什么是相交链表,就是前面是分开的,后面是重叠的,一直重叠到底
解法2,hash的方法,首先hash第一个链表的地址,再遍历第二个链表的地址,看是否在hash表中,时间复杂度O(len(h1)+len(h2)),但是建hash表有额外空间消耗O(len(h1))
解法3,转为判断链表是否有环的问题,见上面5,把第1个链表的尾节点连接第2个链表的头节点,遍历第2个链表,看是否有环(这有个前提,就是一开始给的两个链表无环)
最好的方法解法四,看两个链表的最后一个节点是否相同,即可O(len(h1)+len(h2))
扩展问题:
1.怎样求出两个链表相交的第一个结点,
遍历第一个链表,得到长度len(h1),遍历第二个链表,得到长度len(h2)
看看那个长,再长的链表提前|len(h1)-len(h2)|步开始走,然后比较,直到相等的,即为第一个相交结点。
2.如果链表有环,怎样判断两个链表是否相交
判断第1个链表是否有环,用一快一慢指针,得到一个在环内的结点A(快慢指针重叠的位置)
判断第2个链表是否有环,用一快一慢指针,如果无环--->不相交,如果有环,在得到有(快慢指针重叠的位置还没发现第一个链表的a的话--->不想交,发现--->相交
---------------------------------------------------
19-1:给一个字符串和一个字符集,求该字符串包含字符集的最短子串http://club.itqun.net/showtopic-207005.html
就是给一个很长的字符串str 还有一个字符集比如{a,b,c} 找出str里包含{a,b,c}的最短子串。要求O(n)?
比如,字符集是a,b,c,字符串是abdcaabcx,则最短子串为abc
用两个变量 front rear 指向一个的子串区间的头和尾
用一个int cnt[255]={0}记录当前这个子串里 字符集a,b,c 各自的个数,一个变量sum记录字符集里有多少个了
rear 一直加,更新cnt[]和sum的值,直到 sum等于字符集个数
然后front++,直到cnt[]里某个字符个数为0,这样就找到一个符合条件的字串了
继续前面的操作,就可以找到最短的了
---------------------------------------------------
19-2:5个数排序 要比较的最少次数
7次http://blog.csdn.net/fisher_jiang/archive/2008/05/13/2442486.aspx
---------------------------------------------------
20.Lowest Common Ancestor(待)http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor
---------------------------------------------------
20.背包问题与最小数目硬币(dynamic programming)最小数目硬币,给出一个sum比如11,给出有几种硬币,比如1,3,5,求用最少的硬币数达到sum,这里为551,三枚。见http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg
看看代码很容易明白。sum从1开始遍历,小于sum的都已经计算过了,则遍历一下所有的硬币,如果vj<sum则加进来,sum-vj已经求过了
Set Min[i] equal to Infinity for all of i
Min[0]=0
For i = 1 to S
For j = 0 to N - 1
If (Vj<=i AND Min[i-Vj]+1<Min[i])
Then Min[i]=Min[i-Vj]+1
Output Min[S]
背包问题:见
http://xmuzzx.blog.hexun.com/39126356_d.html
即,看url那个图,即从上到下一项项物品往下遍历
f(i,j)遍历到第i项物品,j为背包的价值容量
if(w[n]<m)
//不把n加进来,和把n加进来取一个最大值,所有的f(n-1,m)的值已经先前计算出来了
f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n)}//p(n)为第n项物品的价值
else
f(n,m)=f(n-1,m)
----------------------------------------
21 从两个文件(各含50亿个url)中找出共同的url
http://mianshiti.blog.sohu.com/144535301.html
可以估计每个文件的大小为5G*64=300G,远大于4G。所以不可能将其完全加载到内存中处理。考虑采取分而治之的方法。
遍历文件a,对每个url求取hash(url)%1000,然后根据所得值将url分别存储到1000个小文件(设为 a0,a1,...a999)当中。这样每个小文件的大小约为300M。遍历文件b,采取和a相同的方法将url分别存储到1000个小文件 (b0,b1....b999)中。这样处理后,所有可能相同的url都在对应的小文件(a0 vs b0, a1 vs b1....a999 vs b999)当中,不对应的小文件(比如a0 vs b99)不可能有相同的url。然后我们只要求出1000对小文件中相同的url即可。
比如对于a0 vs b0,我们可以遍历a0,将其中的url存储到hash_map当中。然后遍历b0,如果url在hash_map中,则说明此url在a和b中同时存在,保存到文件中即可。
如果分成的小文件不均匀,导致有些小文件太大(比如大于2G),可以考虑将这些太大的小文件再按类似的方法分成小小文件即可。
---------------------------------------------
22.有1到10w这10w个数,去除2个并打乱次序,如何找出那两个数?
方法一:
申请10w个bit的空间,每个bit代表一个数字是否出现过。
开始时将这10w个bit都初始化为0,表示所有数字都没有出现过。
然后依次读入已经打乱循序的数字,并将对应的bit设为1。
当处理完所有数字后,根据为0的bit得出没有出现的数字。
方法二:
首先计算1到10w的和,平方和。
然后计算给定数字的和,平方和。
两次的到的数字相减,可以得到这两个数字的和,平方和。
所以我们有
x + y = n
x^2 + y^2 = m
解方程可以得到x和y的值。
---------------------------------------------
23.如何找出字典中的兄弟单词http://mianshiti.blog.sohu.com/144535354.html
问题:
给定一个单词a,如果通过交换单词中字母的顺序可以得到另外的单词b,那么定义b是a的兄弟单词。现在给定一个字典,用户输入一个单词,如何根据字典找出这个单词有多少个兄弟单词?
答案:
使用hash_map和链表。
首先定义一个key,使得兄弟单词有相同的key,不是兄弟的单词有不同的key。例如,将单词按字母从小到大重新排序后作为其key,比如bad的key为abd,good的key为dgoo。
使用链表将所有兄弟单词串在一起,hash_map的key为单词的key,value为链表的起始地址。
开始时,先遍历字典,将每个单词都按照key加入到对应的链表当中。当需要找兄弟单词时,只需求取这个单词的key,然后到hash_map中找到对应的链表即可。
这样创建hash_map时时间复杂度为O(n),查找兄弟单词时时间复杂度是O(1)。
-------------------------------------------
24.海量日志数据,提取出某日访问百度次数最多的那个IP。
IP地址最多有2^32=4G种取值可能,所以不能完全加载到内存中。
可以考虑分而治之的策略,按照IP地址的hash(IP)%1024值,将海量日志存储到1024个小文件中。每个小文件最多包含4M个IP地址。
对于每个小文件,可以构建一个IP作为key,出现次数作为value的hash_map,并记录当前出现次数最多的1个IP地址。
有了1024个小文件中的出现次数最多的IP,我们就可以轻松得到总体上出现次数最多的IP。
----------------------------------------------------
atoi:
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <ctype.h>
4
5 long my_atol(const char *nptr)
6 {
7 int c; /* current char */
8 long total; /* current total */
9 int sign; /* if '-', then negative, otherwise positive */
10
11 /* skip whitespace */
12 while ( isspace((int)(unsigned char)*nptr) )
13 {
14 ++nptr;
15 }
16
17 c = (int)(unsigned char)*nptr++;
18 sign = c; /* save sign indication */
19 if (c == '-' || c == '+')
20 {
21 c = (int)(unsigned char)*nptr++; /* skip sign */
22 }
23
24 total = 0;
25
26 while (isdigit(c))
27 {
28 total = 10 * total + (c - '0'); /* accumulate digit */
29 c = (int)(unsigned char)*nptr++; /* get next char */
30 }
31
32 if (sign == '-')
33 {
34 return -total;
35 }
36 else
37 {
38 return total; /* return result, negated if necessary */
39 }
40 }
strcmp:
int strcmp(const char *src,const char *dst)
{
int ret=0;
while(!(ret=*(unsigned char *)src-*(unsigned char *)dst) && *dst)
++src,++dst;
if(ret<0)
ret=-1;
else if(ret>0)
ret=1;
return ret;
}
memcpy:
void* memcpy( void* dest, const void* src, size_t count )
{
if (count<0){
printf("Invalid count number !.\n");
return (void*)0;
}
if(src==NULL||dest==NULL)
return (void*)0 ;
if ((unsigned int)dest==(unsigned int)src){
printf("The source is equal with the destanation!.\n");
return dest;
}
char* d = (char*)dest;
const char* s = (const char*)src;
while(count--)
*d++ = *s++;
return dest;
}
quickSort:
int arr= {2,3,7,9,5,4,8}; quickSort(0, arr.length-1);//注意是-1 void quickSort(int start, int end){ if(start<end){ int position = partition(start, end); quickSort(start,position-1); quickSort(position+1,end); } } private int partition(int start, int end) { int pivot = arr[end]; int i = start-1; for(int j= start;j<= end-1;j++){ if(arr[j] < pivot){ i+=1; exchange(i,j); } } exchange(i+1, end); return i+1; } void exchange(int p1, int p2){ int temp = arr[p1]; arr[p1] = arr[p2]; arr[p2] = temp; }
前序遍历(非递归实现):
void preTraverse(BNode tree){//如果上面是指针的话,下面定义也是指针 BNode p = tree; BNode stack[200]; int top = 0; while(top >= 0){ while(p!=null){ visit(p);//访问p stack[top++] = p; p = p->leftChild; } if(top > 0){ p = stack[--top]->rightChild; }else{ top = -1; } } }
中序遍历非递归实现(和上面差不多,访问的位置不同):
void preTraverse(BNode tree){//如果上面是指针的话,下面定义也是指针 BNode p = tree; BNode stack[200]; int top = 0; while(top >= 0){ while(p!=null){ stack[top++] = p; p = p->leftChild; } if(top > 0){ p = stack[--top] visit(p);//访问p p = p->rightChild; }else{ top = -1; } } }
发表评论
-
项目备忘
2010-09-06 16:41 1094[/color]待,[color=red]svm 分 ... -
多线程学习备忘
2010-08-31 20:23 1262同步,异步,阻塞,非阻塞http://kalogen.itey ... -
面试的一些题
2010-08-24 11:18 13791.stl vector list deque的区别 http ... -
jsp servlet spring备忘
2010-08-22 20:11 11351.fu7.服务器将一个jsp编 ... -
java知识,待
2010-08-19 21:37 974http://blog.sina.com.cn/s/blog_ ... -
位运算 bit
2010-06-22 15:11 9331. a<<b => a*2^b ; a ... -
(math) SmoothNumbersHard --largest prime factor(最大质数因子)
2010-06-18 16:38 1276http://www.topcoder.com/tc?modu ... -
(sort)VoteRigging --a simple problem
2010-06-18 16:33 977VoteRigging http://www.topcoder ... -
(dp)MarblesRegroupingHard --bigraph mincost
2010-06-18 14:29 1030MarblesRegroupingHard http://ww ... -
一些试题的链接
2009-12-16 15:54 1014http://www.mianwww.com/ 面试:大数据 ...
相关推荐
* 配备学习资源:选择适合自己的学习资源,包括教材、真题、练习题等。 * 练习和反馈:通过练习和反馈来提高自己的英语水平,包括阅读、写作、听力等多个方面。 * Simulation 测试:通过 Simulation 测试来提高自己...
亲爱的[题干称呼], 我非常荣幸地邀请您参加+[参加的活动的名称],本次活动由[某人或组织]举办,将在+[活动举办的时间]于[活动举办的地点]举行。我们非常期待您的光临。 活动将于+[具体时间+具体地点]开始,随后将...
那建立一个工程把代码放到工程中,这样又可以保存代码,又可以实现功能,不过这样也太小题大作了。本软件就可以帮你把你看的小东西用数据库的方式保存起来,而且查找方便,只要你保存合理,这些有用的代码将让你受益...
师生交流系统,在线题库系统,基于android的备忘录,android的计算器,C#贪吃蛇
5. **技术面试技巧**:学习如何清晰地阐述自己的技术思路,能够解释代码逻辑,同时准备一些常见面试问题,比如系统设计问题或算法题。 6. **公司研究**:对邀请面试的公司进行深入了解,包括公司业务、产品、技术栈...
在《昆虫备忘录》课时练的汉字拼音选择题中,学生需要根据汉语拼音的基本规则,正确地识别和选择汉字的标准读音。例如,“目录”一词的正确读音是“lù mù”,这不仅考察了学生对单个汉字拼音的掌握,还考查了他们...
设计模式通常分为三类:创建型模式(如工厂方法、抽象工厂、单例、建造者、原型)、结构型模式(如适配器、桥接、装饰、组合、代理、外观、享元)和行为型模式(如责任链、命令、解释器、迭代器、访问者、备忘录、...
3. **行为型模式**:包括策略(Strategy)、模板方法(Template Method)、观察者(Observer)、迭代器(Iterator)、访问者(Visitor)、责任链(Chain of Responsibility)、命令(Command)、备忘录(Memento)、...
7. **CheatSheet-Python-6_-Coding-Interview-Questions.pdf**:这份面试问题速查表可能包含了一些常见的Python编程面试题,如算法、数据结构和问题解决策略,帮助准备面试者提高解决问题的能力。 8. **CheatSheet-...
所以,给自己整理一份iOS面试题备忘录,拯救那糟糕的记忆力和表达力。 iOS面试题备忘录包含初级、中级和高级面试题,试题来源于网络(已标明出处,如遗漏,请告知)、网课和自己的总结,有回答不正确或者不完善的地方...
标题“POI word目录处理备忘”涉及到的是Apache POI库在处理Microsoft Word文档时,尤其是涉及Word文档目录(TOC,Table of Contents)的操作。Apache POI是一个流行的开源Java库,它允许开发者读取、写入和修改...
在本题中,回文自动机用于构建和维护字符串的回文性质。 3. **Floyd算法**(fail树):Floyd算法是构建回文自动机的一种方法,通过不断扩展字符集中的字符,更新每个状态的转移,最终得到一个fail树。在回文自动机...
18. **备忘录模式(Memento)**:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将对象恢复到原先保存的状态。 19. **观察者模式(Observer)**:定义对象间的一种一...
- 行为型模式:策略、模板方法、观察者、责任链、迭代器、访问者、命令、备忘录、状态、解释器。 4. **Java集合框架** - List接口:ArrayList、LinkedList的区别与使用场景。 - Set接口:HashSet、TreeSet的区别...
- 可以进一步增加学生的自主选择权,让他们选择自己感兴趣的昆虫进行深入学习,以提高学习的积极性。 #### 备课素材分析 - **教材分析**:本文选自部编版小学语文教材,是一篇适合三年级学生的科普文章,内容活泼...
│ JAVA笔试题(上海释锐).pdf │ MIME简介.txt │ SCJP试题详解.pdf │ SQL面试题_心灵深处.htm │ Struts+Hibernate+Spring轻量级J2EE企业应用实战.pdf │ Struts中文手册.pdf │ Struts配置文件详解.txt │ 上海...
行为型模式有十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。 3. 死锁的原因有两个:多个线程涉及到多个锁,这些锁...
│ JAVA笔试题(上海释锐).pdf │ MIME简介.txt │ SCJP试题详解.pdf │ SQL面试题_心灵深处.htm │ Struts+Hibernate+Spring轻量级J2EE企业应用实战.pdf │ Struts中文手册.pdf │ Struts配置文件详解.txt │ 上海...
单例模式:单例模式属于创建型模式,一个单例类在任何情况下都只存在一个实例,构造方法必须是私有的、由自己创建一个静态变量存储实例,对外提供一个静态公有方法获取实例。 这些设计模式都是软件开发人员需要了解...