随笔分类 -  数据结构与算法

快速排序算法(Quicksort)
摘要:快速排序算法是对集合中元素进行排序最通用的算法,俗称快排,其算法的时间复杂度为O(nlgn),空间复杂度为O(1)。我们举例来对其算法思路进行理解,譬如数组 A = { 4, 8, 1, 2, 9, 7, 3, 0, 5, 6 };第一步,以最后一个数6为基准,把小于等于6的数挪到数组左边,把大于6... 阅读全文

posted @ 2016-01-01 08:13 NULL00 阅读(5262) 评论(0) 推荐(1) 编辑

面试题笔记
摘要:反转一个无符号整数的比特位.Reverse the bits of an unsigned integer.For example, x is 0x00001234, then reverse(x) is 0x2C480000.static uint Reverse(uint x){ uint... 阅读全文

posted @ 2013-02-07 10:50 NULL00 阅读(1502) 评论(1) 推荐(2) 编辑

N个鸡蛋放进M个篮子问题
摘要:题目:有N个鸡蛋和M个篮子,把鸡蛋放到M个篮子里,每个篮子都不能为空。另外,需要满足:任意一个小于N的正整数,都能由某几个篮子内蛋的数量相加的和得到。写出程序,使得输入一个(N,M),输出所有可能的分配情况。从题意中应该可以得出,对于(1,1,2,2)和(1,2,1,2)这两种组合,应该是一样的。因而对于这M个篮子中的鸡蛋数量,我们用数组basket[M]来表示,我们按照非递减顺序进行排列,即basket[i] <= basket[i+1]1.我们利用归纳法来总结出一个规律: 对于前n个篮子,其鸡蛋数量总和为Sn,那么对于第n+1个篮子,其鸡蛋数量应该满足: basket[n+1] &l 阅读全文

posted @ 2012-06-20 14:25 NULL00 阅读(6752) 评论(4) 推荐(2) 编辑

treap(树堆)
摘要:一棵treap是一棵修改了结点顺序的二叉查找树,如图,显示一个例子,通常树内的每个结点x都有一个关键字值key[x],另外,还要为结点分配priority[x],它是一个独立选取的随机数。假设所有的优先级是不同的,所有的关键字也是不同的。treap的结点排列成让关键字遵循二叉查找树性质,并且优先级遵循最小堆顺序性质:1.如果v是u的左孩子,则key[v] < key[u].2.如果v是u的右孩子,则key[v] > key[u].3.如果v是u的孩子,则priority[u] > priority[u].这两个性质的结合就是为什么这种树被称为“treap”的原因,因为它同时具 阅读全文

posted @ 2012-05-06 13:06 NULL00 阅读(12670) 评论(1) 推荐(0) 编辑

Trie树|字典树(字符串排序)
摘要:有时,我们会碰到对字符串的排序,若采用一些经典的排序算法,则时间复杂度一般为O(n*lgn),但若采用Trie树,则时间复杂度仅为O(n)。Trie树又名字典树,从字面意思即可理解,这种树的结构像英文字典一样,相邻的单词一般前缀相同,之所以时间复杂度低,是因为其采用了以空间换取时间的策略。下图为一个针对字符串排序的Trie树(我们假设在这里字符串都是小写字母),每个结点有26个分支,每个分支代表一个字母,结点存放的是从root节点到达此结点的路经上的字符组成的字符串。将每个字符串插入到trie树中,到达特定的结尾节点时,在这个节点上进行标记,如插入"afb",第一个字母为a 阅读全文

posted @ 2012-05-05 13:04 NULL00 阅读(9069) 评论(4) 推荐(3) 编辑

判断单链表是否有环的两种方法
摘要:如图,如果单链表有环,则在遍历时,在通过6之后,会重新回到3,那么我们可以在遍历时使用两个指针,看两个指针是否相等。方法一:使用p、q两个指针,p总是向前走,但q每次都从头开始走,对于每个节点,看p走的步数是否和q一样。如图,当p从6走到3时,用了6步,此时若q从head出发,则只需两步就到3,因而步数不等,出现矛盾,存在环方法二:使用p、q两个指针,p每次向前走一步,q每次向前走两步,若在某个时候p == q,则存在环。代码如下: 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define LEN 8 5 typede 阅读全文

posted @ 2012-05-03 14:06 NULL00 阅读(16778) 评论(2) 推荐(1) 编辑

从数组中取出n个元素的所有组合(递归实现)
摘要:今天在做POJ 1753时,需要枚举一个数组中所有组合。之前也遇到过类似的问题,如求从n个数组任意选取一个元素的所有组合都是想起来比较简单,但是设计成算法却颇费周折。如数组为{1, 2, 3, 4, 5, 6},那么从它中取出3个元素的组合有哪些,取出4个元素的组合呢?比如取3个元素的组合,我们的思维是:取1、2,然后再分别取3,4,5,6;取1、3,然后再分别取4,5,6;......取2、3,然后再分别取4,5,5;......这样按顺序来,就可以保证完全没有重复。这种顺序思维给我们的启示便是这个问题可以用递归来实现,但是仅从上述描述来看,却无法下手。我们可以稍作改变:1.先从数组中A取出 阅读全文

posted @ 2012-04-27 16:35 NULL00 阅读(39628) 评论(4) 推荐(6) 编辑

散列表(Hash Table)总结
摘要:复习了下散列表(Hash Table),总结如下:1.直接寻址表 直接送数组进行对应,但是当要存储的关键字集合K相对于域U很小时,就会很浪费空间。2.散列表 利用Hash函数进行映射 “碰撞”发生时,利用链接法解决3.散列函数的选择 3.1除法散列表 h(k) = k mod m,m是与2的整数幂不太接近的质数 3.2乘法散列表 h(k) = 【m*(k*A mod 1)】向下取整,其中A最好取0.618....... 3.3全域散列 ha,b(k) = ((a*k + b) mod p) mod m,a属于{1, 2 ..., p-1},b属于{0, 1 ..., p-1}... 阅读全文

posted @ 2012-04-25 14:45 NULL00 阅读(1152) 评论(3) 推荐(0) 编辑

线段树(segment tree)
摘要:线段树在一些acm题目中经常见到,这种数据结构主要应用在计算几何和地理信息系统中。下图就为一个线段树:(PS:可能你见过线段树的不同表示方式,但是都大同小异,根据自己的需要来建就行。)1.线段树基本性质和操作线段树是一棵二叉树,记为T(a, b),参数a,b表示区间[a,b],其中b-a称为区间的长度,记为L。线段树T(a,b)也可递归定义为:若L>1 : [a, (a+b) div 2]为 T的左儿子; [(a+b) div 2,b]为T 的右儿子。 若L=1 : T为叶子节点。线段树中的结点一般采取如下数据结构:struct Node{ int left... 阅读全文

posted @ 2012-04-22 03:25 NULL00 阅读(41023) 评论(7) 推荐(9) 编辑

求从n个数组任意选取一个元素的所有组合
摘要:求从n个数组任意选取一个元素的所有组合,对于这个问题,我们在直观上感觉很容易,但是用程序实现时则发现用for循环解决不了问题,因为n是随意的。在这里,我们用递归的思想,对于数据[1, 3, 4]; [2, 5]; [6, 7];我们可以1.将1,2,6压入栈中,然后输出栈中所有元素,之后弹出62.压入7,输出栈中所有元素,之后弹出73.弹出2,压入5,再压入6,然后输出栈中所有元素,之后弹出64.压入7,输出栈中所有元素,之后弹出7以此类推,即可得到所有组合。具体程序实现如下:#include <iostream>#include <vector>#include &l 阅读全文

posted @ 2011-06-15 15:39 NULL00 阅读(5841) 评论(1) 推荐(2) 编辑

编程珠玑-位排序(bitsort)
摘要:在《编程珠玑》一书上,有一题是将一堆不重复的数进行排序,这些数的值大小位于[0, 10000000).然后作者在书后给出的答案确实很精辟,利用位排序将这个问题轻而易举的解决了。 首先弄懂i>>SHIFT相当于i/32,i&MASK相当于i%32. 题目中说了 Replace above 2 line 阅读全文

posted @ 2011-05-29 01:36 NULL00 阅读(4458) 评论(4) 推荐(1) 编辑

最长公共子序列(LCS)
摘要:对于最长公共子序列(LCS),是典型的动态规划问题,对于这个问题,可以用如下思路来解答。如:X{x1, x2, x3, ... },Y{y1, y2, y3, ...};1.当x1 = y1时,则此时已找到一个相同的值,故接下来只需求{x2, x3, x4, ...}和{y2, y3, y4, ...}的LCS。2.当x1 != y1时,则此时X和Y的LCS是下面两个LCS的最大值: {x2, x3, x4, ...}和{y1, y2, y3, y4, ...}的LCS, 或者{x1, x2, x3, x4, ...}和{y2, y3, y4, ...}的LCS。由上面可以看出这是一个递归问题 阅读全文

posted @ 2011-05-27 21:24 NULL00 阅读(1953) 评论(3) 推荐(1) 编辑

删除单链表中偶数节点
摘要:题目意思就是:删除链表中第2个节点,第4个节点......,即删除所有第偶数个节点#include <stdio.h>#include <stdlib.h>#define LEN 8typedef struct node node_t;struct node{ int val; node_t *next; }; //delete even nodevoid delete_even_node(node_t* head);int main(){ node_t** arr = (node_t**)malloc(sizeof(node_t*)*LEN); arr[0] = (n 阅读全文

posted @ 2011-05-13 15:12 NULL00 阅读(5234) 评论(0) 推荐(0) 编辑

单链表反转
摘要:void reverse(List* list){ Node* before = list->first; if (before != NULL) { Node* after = before->next; before->next = NULL; while (after) { //交换指针 Node* temp = after->next; after->next = before; before = after; after = temp; } }} 阅读全文

posted @ 2011-05-09 21:43 NULL00 阅读(454) 评论(0) 推荐(0) 编辑

非递归实现fibonacci数列
摘要:下面用两个方法实现fibonacci数列,一个是递归的,一个是非递归的,由于递归需要不断的开辟新的栈,并释放开辟的栈,因而更耗时,但是在理解上却容易些。#include <iostream>#include <time.h>using namespace std;int recursive_method(int n);int non_recursive_method(int n);int main(){ clock_t t3 = clock(); printf("%d\n", non_recursive_method(40)); clock_t t4 阅读全文

posted @ 2011-05-09 21:34 NULL00 阅读(2762) 评论(0) 推荐(0) 编辑

shell(希尔)排序
摘要:shell(希尔)排序是一种改进的插入排序(链接),如对数组{4, 7, 2, 8, 5, 1, 3, 6},取距离增量为d = 8/2 = 4,形式上将数组分为了4组,4 7 2 85 1 3 6每一列为一组,组内排序后为4 1 2 65 7 3 8,即排序后的数组为{4 1 2 6 5 7 3 8},再取距离增量为d = 4/2 = 2,则可分为2组,每一列为一组4 12 65 73 8,组内排序后为2 13 64 75 8排序后的数组为{2 1 3 6 4 7 5 8},然后采用插入排序即可。下面的shell_sort函数为<<C programming language&g 阅读全文

posted @ 2011-05-08 23:34 NULL00 阅读(303) 评论(0) 推荐(0) 编辑

找出输入区间内的回文质数
摘要:假设输入区间为[a, b],a>0,则回文质数满足以下条件:1.为质数(废话)2.必须为回文数(正着看倒着看是一样),但这个回文数的位数必须为奇数位(11除外),为什么呢? 因为位数为偶数的回文数必然是11的倍数,即它不是质数,具体证明如下: 对于数字abcd,abcd = 1000*a + 100*b + 10*c + d = (1100*a - 110*a + 11*a - a) + (110*b - 11*b + b) + (11*c - c) + d = (1100*a - 110*a + 11*a) + (110*b - 11*b) + 11*c + (b + d - a - 阅读全文

posted @ 2011-05-07 21:30 NULL00 阅读(1179) 评论(0) 推荐(0) 编辑

KMP算法源码实现
摘要:对于KMP算法的讲解,Matrix67在这里给出了很详细的解释,我在这里只是实现了相关源码而已,以作备用。#include <iostream>using namespace std;const int* get_substring_arr(const char* sequence);void kmp(const char* src, const char* substring, const int* a);int main(){ char* src = "acabaabaabcacaabc"; char* substring = "abaabcac& 阅读全文

posted @ 2011-05-04 14:53 NULL00 阅读(1380) 评论(0) 推荐(0) 编辑

二叉查找树实现源码
摘要:看了《算法导论》上的第12章二叉查找树,现把对二叉树的几种操作罗列如下,实现的描述见代码注释。#include <iostream>using namespace std;class Node{public: int key; Node* left; Node* right; Node* parent; Node(int k);};class BinarySearchTree{public: Node* root; BinarySearchTree(); //以node为根节点开始搜索 Node* search(Node* node, int k); //插入节点 void ins 阅读全文

posted @ 2011-04-28 22:41 NULL00 阅读(412) 评论(0) 推荐(0) 编辑

二分查找算法
摘要:二分查找算法是在有序数组中用到的较为频繁的一种算法,在未接触二分查找算法时,最通用的一种做法是,对数组进行遍历,跟每个元素进行比较,其时间为O(n).但二分查找算法则更优,因为其查找时间为O(lgn),譬如数组{1, 2, 3, 4, 5, 6, 7, 8, 9},查找元素6,用二分查找的算法执行的 阅读全文

posted @ 2011-04-15 17:31 NULL00 阅读(123575) 评论(3) 推荐(1) 编辑

导航