
数据结构/算法
文章平均质量分 50
jiangyi711
这个作者很懒,什么都没留下…
展开
-
非递归遍历二叉树
<br />//// 非递归中序遍历二叉树//void InOrder(struct Node* root){ if (root == NULL) return; struct Node *t = root; stack<struct Node*> s; while (t != NULL || !s.empty()) { while (t != NULL) { s.push(t); // 压栈 t =原创 2010-10-22 13:50:00 · 1976 阅读 · 0 评论 -
微软,Google面试题 (22) —— 跳台阶
题目:一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。求总共有多少总跳法,并分析算法的时间复杂度。解法一:就是一个Fibonacci数列的问题。1. f(1) = 1; 只有一阶台阶的时候,只有一种跳法2. f(2) = 2; 有两节台阶的时候,有两种跳法。3. f(n) = f(n-1) + f(n-2)。这个和之前的“10枪打90环”问题类似,那个问题只不过是Fibonacci数列的一个扩大。原创 2010-08-25 02:00:00 · 1040 阅读 · 0 评论 -
微软,Google面试题 (19) —— 反转单向链表
题目:输入一个链表的头结点,反转该链表,并返回反转后链表的头结点。链表结点定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};解法一:起始节点为p1,令p2 = p1->next, p1->next = NULL。若p2为NULL,则返回p1;若p2不为NULL,进行如下循环:令p3 = p2->next。p2->next = p1;然后再令p1 = p2; p2 = p3;直到p2为NULL,退出循环。原创 2010-08-24 12:55:00 · 1382 阅读 · 0 评论 -
微软,Google面试题 (27) —— 二元树的深度
题目:输入一棵二元树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。例如:输入二元树: 10 / / 6 14原创 2010-08-25 15:26:00 · 822 阅读 · 0 评论 -
微软,Google面试题 (26) —— 和为n连续正数序列
题目:输入一个正数n,输出所有和为n连续正数序列。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5、4-6和7-8。解法一:开辟一个大小为n/2 + 1(n为奇数,n为偶数则大小为n/2 - 1)的数组,值从1到n。两个指针p1指向1,p2指向p1的下一个。然后循环,如果p1和p2之间的元素和小于n,p2++;大于n,p1++;等于n,则输出之后p1,p2同时后移。直到p2走完数组,循环结束。这种方法时间复杂度为O(n),空间复杂度为O(n)。解法二:常规解法,复杂原创 2010-08-25 15:13:00 · 1024 阅读 · 2 评论 -
微软,Google面试题 (24) —— 栈的push、pop序列
题目:输入两个整数序列。其中一个序列表示栈的push顺序,判断另一个序列有没有可能是对应的pop顺序。为了简单起见,我们假设push序列的任意两个整数都是不相等的。例一:push序列为12345,pop序列为45321解法一:设计一个辅助栈。第一个pop的为4,将push序列中4之前所有元素push进栈。然后将4 push再pop。第二个为5,此时栈顶元素为3。继续遍历push序列,将5之前的所有元素push,然后将5 push再pop。下一个pop的喂3,刚好是栈顶。这样直到把所有元素都pop。例二:pu原创 2010-08-25 15:01:00 · 1278 阅读 · 0 评论 -
微软,Google面试题 (14) —— 约瑟夫环
题目:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。当一个数字删除后,从被删除数字的下一个继续删除第m个数字。求出在这个圆圈中剩下的最后一个数字。解法一:序号为0到n-1,则删除的数的序号为(m-1)%n,第二次就从m%n开始。所以有:序列一:0,1,2,3,....,n-1序列二:0,1,2,3,...m-2,m,m+1,....n-1序列三:m,m+1,...n-1,0,1....m-2序列四:0, 1,2原创 2010-08-24 01:07:00 · 957 阅读 · 0 评论 -
微软,Google面试题 (12) —— 从上往下遍历二叉树
题目:输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。例如输入 8 / / 6 10 // // 5 7 9 11输出8 6 10 5 7 9 11。解法:树是图的一种特殊的退化形式。本题就是一个广度优先遍历图的问题。首先把root放进一个队列。开始循环,当队列不为空的时候。pop并且打印队首元素。然后把对手元素的孩子节点从左到右依次push进队列。继续循环。void BSF(Node* root){原创 2010-08-23 22:54:00 · 888 阅读 · 0 评论 -
微软,Google面试题 (10) —— 在排序数组中寻找两个数的和等于给定数
题目:输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。解法一:常规解法。对于每一个数组元素k,寻找n-k有没有在余下的数组里面,这种方法的时间复杂度为O(n^2)。解法二:两个指针begin和end分别指向数组的头和尾。如果*begin + *end大于n,begin向后移动一位。如果小于n,en转载 2010-08-23 21:50:00 · 1957 阅读 · 1 评论 -
微软,Google面试题 (7) —— 反转句子中单词的顺序
题目:输入一个英文句子,反转句子中单词的顺序,但单词内字符的顺序不变。句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。例如输入“I am a student.”,则输出“student. a am I”。思路:首先反转所有字符,然后再依次反转每一个单词(以空格区分)。原创 2010-08-23 02:06:00 · 1441 阅读 · 0 评论 -
微软,Google面试题 (32) —— O(1)时间删除节点
Google面试题:给定链表的头指针和一个结点指针,在O(1)时间删除该结点。解法一:将该节点的next的value复制给该节点,删除next。如果给出的节点为最后一个节点,则必须遍历链表。平均复杂度为O(1)。转载 2010-08-25 16:02:00 · 2199 阅读 · 0 评论 -
微软,Google面试题 (21) —— 左旋字符串(循环移位)
题目:定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。如把字符串abcdef左旋转2位得到字符串cdefab。请实现字符串左旋转的函数。要求时间对长度为n的字符串操作的复杂度为O(n),辅助内存为O(1)。解法一:不考虑时间和空间的限制。设移动的位数为k。则循环k次,每次移动1位。这样的空间复杂度是O(1),时间复杂度是O(n*k)。如果k小于n,则O(n^2)。解法二:最直接的方法。开辟一块大小为n的内存,将前k个字符拷贝到后k个位置。将后面的n-k个字符拷贝到新空间前n-k个位置。这原创 2010-08-25 01:45:00 · 2376 阅读 · 0 评论 -
微软,Google面试题 (28) —— 字符串的排列
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。和http://blog.youkuaiyun.com/jiangyi711/archive/2010/08/22/5830737.aspx类似。考察递归。解法一:每层递归都有一个循环。循环做的工作是将某一段的每一个字符都交换到这段字符串的开头。当字符串长度为1时,打印。原创 2010-08-25 15:38:00 · 812 阅读 · 0 评论 -
STL 中几个简单的数值算法实现
复习《STL源码剖析》,先把几个简单的算法自己实现一下。参数没有用迭代器,直接用整型数组。#include #include /* 应用于有序区间,判断 b 中的元素是否全部被 a 包含。默认为升序,如果为降序,改变比较符号即可*/bool includes(int* a, size_t al, int *b, size_t bl){ size_t i = 0, j = 0; while (i b[j]) return false; else if原创 2010-10-10 23:50:00 · 2024 阅读 · 0 评论 -
利用归并排序求数列中逆序对个数
参考了这篇文章:http://blog.youkuaiyun.com/MapReduce/archive/2007/05/20/1618515.aspx以前自己写的归并排序比较累赘,文章中的代码更有条理,而且计算逆序对个数只需要一行代码,是否对原数列进行排序也只需要决定是否取舍一行代码。#include #include int ans;void copy(int a[], int b[], int l, int r){ int i = l; while (i原创 2010-10-08 01:31:00 · 3162 阅读 · 0 评论 -
几个集合算法
上有相应的详细算法,我这里只写出了适用于普通指针的算法,思路和书上的一样。1. 交集void set_intersection(int a[], size_t al, int b[], size_t bl){ size_t i = 0, j = 0; while (i b[j]) j++; else { printf("%d ", a[i]); i++, j++; } } printf("/n");}原创 2010-10-07 21:55:00 · 1962 阅读 · 0 评论 -
Range Minimum Query (RMQ)
解法一:Sparse Table (ST) algorithm对2k 的长度的子数组进行动态规划。我们将使用数组M[0, N-1][0, logN]进行保存,其中M[i][j]是以i 开始,长度为 2j的子数组的最小值的索引。一旦我们预处理了这些值,让我们看看怎样使用它们去计算RMQA(i, j)。思路是选择两个能够完全覆盖区间[i..j]的块并且找到它们之间的最小值。设k = [log(j - i + 1)].。为了计算RMQA(i, j) 我们可以使用下面的公式这个算法的总的时间复杂度为 const i转载 2010-10-04 00:44:00 · 2099 阅读 · 0 评论 -
Trend Micro 2011 笔试题
求一个字符串的最长不重复子串长度。如 "abcdefgd"的最长不重复子串为"abcdefg",长度为7。在做题的时候没带草稿纸,导致试卷上有很多涂改,而且还忘记处理字符串结尾部分。#include #include #include using namespace std;int search(char* str, int len){ map m; if (len (str[p1], p1)); while (p2 second; if (p2原创 2010-10-01 14:13:00 · 2107 阅读 · 0 评论 -
单源最短路径 :Dijkstra 算法
Dijkstra 算法用于解决有向图的最短路径问题。算法描述如下:1. 初始化原点的距离为0,到其他任意点到原点的距离为无穷大。2. 初始化已访问节点集合为空,未访问节点集合为所有节点。3. 在未访问节点集合中找到一个到已访问节点集合距离最近的节点(第一次找到的节点为原点),将该节点加入已访问节点。4. 更新该节点的邻居节点中处于未访问状态的节点的距离。5. 重复第三步。直到所有节点都已经访问。下面是一个最基本的Dijkstra 算法的c++实现,有向图存储采用的是邻接矩阵。const int MAXN =原创 2010-10-05 17:09:00 · 2215 阅读 · 0 评论 -
KMP算法
根据matrix67博客上的思路,自己实现的kmp算法,字符串下标从0开始。#include #include const int MAXN = 1000;int P[MAXN];void pre(const char* B){ P[0] = -1; int i, j = -1; for (i = 1; i -1 && B[j+1] != B[i]) j = P[j]; if (B[j+1] == B[i]) j++; P[i] = j;原创 2010-09-29 16:56:00 · 1775 阅读 · 0 评论 -
微软,Google面试题 (31) —— 从尾到头输出链表
题目:输入一个链表的头结点,从尾到头反过来输出每个结点的值。链表结点定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};解法一:从头遍历链表,把每个节点的值push到一个栈中。解法二:递归思想。递归输出next节点,然后输出自己节点的value。让next为NULL,递归return。转载 2010-08-25 15:57:00 · 2014 阅读 · 0 评论 -
微软,Google面试题 (29) —— 调整数组顺序使奇数位于偶数前面
题目:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为O(n)。解法一:遍历数组,遇到偶数。取出该值,然后将该值后面的元素依次向前移动一位。然后将该值放到数组的最后一位。这种方法复杂度为O(n^2)。解法二:快排思想。转载 2010-08-25 15:46:00 · 820 阅读 · 0 评论 -
微软,Google面试题 (8) —— 求1+2+...+n
题目:求1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句(A?B:C)。解法一:用递归,利用&&运算符的特性做。解法二:用构造函数做。class内含有一个static变量,初始化为1。一个全局变量sum初始化为0。在构造函数内部首先sum += i;然后i++。构造一个大小为n,类型类class的数组,调用构造函数n次。即可获得sum。解法三:在递归的思想上,利用c++的多态性来当做递归return的条件。还利用了连续两次!!n,将n转化转载 2010-08-23 02:32:00 · 1829 阅读 · 0 评论 -
10枪打90环,一共多少可能
递归求解,每一枪可以打0环到10环。每一个状态都有11个分支,每一个状态的可能性就等于这11个分支的可能性之和。递归过程中采用记忆化搜索。#include using namespace std;int matrix[91][11];int total = 0; int f(int a, int b){ if (matrix[a][b] != -1) { return matrix[a][b]; } if (b * 10原创 2010-08-23 01:18:00 · 1746 阅读 · 0 评论 -
俄罗斯套娃
记忆化搜索,类似于POJ 1088#include #include #include #include #include #include using namespace std;int row, col;int cnt;int **matrix;int **assist;vector ***path;int getSum (const vector &array) { int i, ret = 0; for (i原创 2010-06-07 15:06:00 · 942 阅读 · 0 评论 -
微软,Google面试题 (5) —— 查找最小的k个元素
输入n个数,找出其中最小的k个。一般的思路是将这n个数排序,排在最前面的k个数就是答案。这种方法最快时间复杂度为nlog(n)。如果再开辟一个长度为k的数组。以此读取这n个数,如果k数组没有满,则直接放入k数组中,如果满了,且当前的数比k数组中最大的数要小,那么就用当前的数替换k数组中最大的数。(实际上,k数组是一个大顶堆)。这样,当n个数读取完之后,k数组中就是最小的k个数。这时候的复杂度为nl原创 2010-03-08 22:25:00 · 1713 阅读 · 0 评论 -
微软,Google面试题 (4) —— 在二叉树中找出和为某一值的所有路径
输入一颗二叉树,从根节点到叶子节点的所有节点构成一条路径,打印出和与输入整数相等的所有路径#include //思路很简单,遍历所有路径void getPath(struct treeNode* node, int sum, vector& stack, int currentSum) { //stack用来存放路径 if (node == NULL)原创 2010-03-08 22:03:00 · 1467 阅读 · 0 评论 -
微软,Google面试题 (3) —— 求最大子数组和
#include #include //求最大子数组和int getSum_v1(int *a, int length) { //穷举所有的子数组,找出和最大的 int greaterSum = 0; int max = 0; for (int len=1; len<=length; ++len) { for (int idx=0; idx<len; ++i原创 2010-03-07 16:57:00 · 753 阅读 · 0 评论 -
微软,Google面试题 (1) —— 把二叉排序树转变成排序的双向链表
#include #include using namespace std;struct treeNode { int id; struct treeNode *lchild; struct treeNode *rchild;};void insert(struct treeNode*& node, int x) { if (node == NULL) {原创 2010-03-04 22:01:00 · 882 阅读 · 0 评论 -
微软,Google面试题 (2) —— 设计带有min函数的栈
#include #include //设计带有min函数的栈struct stack { int element[100]; //栈的大小为100 int *bottom; int *top;};//指针a指向辅助栈void push(struct stack* s, struct stack* a, int x) { if原创 2010-03-07 16:50:00 · 996 阅读 · 0 评论 -
反转单向链表
#include #include #include struct listNode { int id; struct listNode *next;};struct listNode* ReverseIteratively(struct listNode* head) { assert(head != NULL); struct listNode *ptr1原创 2010-03-04 21:57:00 · 520 阅读 · 0 评论 -
用4种不同的方法反转字符串
#include #include #include void strrev_v1(char* src) { assert(src != NULL); if (strlen(src) == 1) return; char *head = src; char *tail = src + strlen(src) - 1; char temp = ;原创 2010-03-04 21:46:00 · 529 阅读 · 0 评论 -
几个简单排序算法
这个是以前写的几个简单的排序算法,比较少。最近在开始看算法和数据结构方面的书,以后会慢慢增加内容 #include #include #include using namespace std;void SelectSort(int a[],int size);void BubbleSort(int a[],int size);void InsertSort(int a原创 2009-11-09 20:59:00 · 605 阅读 · 0 评论 -
动态规划 : 最长公共子串
求str1和str2的最长公共子序列的长度。定义状态pf[i][j]表示分别以str1[i],str2[j]结尾的连续公共子串的长度。所以对于pf[i+1][j+1],有两种情况:1. str1[i+1] != str2[j+1],则pf[i+1][j+1] = 0;2. str1[i+1] = str2[j+1],则pf[i+1][j+1] = pf[i][j] + 1;代码如下:#include #include int maxCommStr(char* str1, char* str2)原创 2010-08-12 23:45:00 · 608 阅读 · 0 评论 -
判断回文数
随机输入一个数,判断是不是回文数。#include using namespace std;bool judgeSymmetry(long n){ int ret = 0, t = n; while (t > 0) // 将高低位互换 { ret = ret * 10 + t % 10; t = t / 10; }; return (ret == n);} int main(){ int n原创 2010-08-13 23:09:00 · 1529 阅读 · 0 评论 -
筛法求素数
<br />筛法,是求不超过自然数N(N>1)的所有质数的一种方法。据说是古希腊的埃拉托斯特尼(Eratosthenes,约公元前274—194年)发明的,又称埃拉托斯特尼筛子。<br />具体做法是:先把N个自然数按次序排列起来。1不是质数,也不是合数,要划去。第二个数2是质数留下来,而把2后面所有能被2整除的数都划去。2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。这样一直做下去,就会把不超过N的全部合数原创 2010-08-14 00:35:00 · 568 阅读 · 0 评论 -
微软,Google面试题 (16) —— O(logn)求Fibonacci数列
题目:定义Fibonacci数列如下: / 0 n=0f(n)= 1 n=1 / f(n-1)+f(n-2) n=2输入n,用最快的方法求该数列的第n项。解法一:常规解法。用递归做。不采取任何优化。int Fibonacci(int n){ if (n == 0 || n == 1) { return n; }原创 2010-08-24 01:27:00 · 1216 阅读 · 0 评论 -
微软,Google面试题 (13) —— 第一个只出现一次的字符
题目:在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。解法一:常规解法。遍历字符串,访问到每一个字符时,检查后面有没有相同的字符。没有则输出。这种做法的时间复杂度是O(n^2)。解法二:利用hashtable。首先为建立一个256大小(ASCII字符的最大值)的hashtable。遍历一次字符串,将每个字符串出现的次数存放在hashtable之中。再遍历一次hashtable,找到第一个次数为1的。转载 2010-08-23 23:01:00 · 723 阅读 · 0 评论 -
微软,Google面试题 (6) —— 判断整数序列是不是二元查找树的后序遍历结果
输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。如果是返回true,否则返回false。例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果: 8 / / 6 10 / / / / 5 7 9 11因此返回true。如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。思路:首先找到数组的最后一个元素,该元素为root。从后往前遍历,直到遇见第一个比root小的元素k原创 2010-08-23 02:02:00 · 714 阅读 · 0 评论 -
微软,Google面试题 (18) —— 用两个栈实现一个队列
解法:有两个栈A和B。队列的appendTail操作为,将元素push进A。队列的deleteHead操作为:如果B不为空,则pop栈B的栈顶元素。如果B为空,则将A中的元素全部依次pop到B,然后pop栈B的栈顶元素。扩展问题:如何用两个队列实现一个栈。解法一:有两个队列C和D。栈的push操作为:1, 将新元素添加到C的尾端。2, 如果C中只有一个元素,则不做任何工作。如果C中有超过1个元素,那么将队列C除队尾的新元素之外的其他元素依次pop,并且添加到D的尾端。保持C中只有一个元素。栈的pop操作为:原创 2010-08-24 02:47:00 · 903 阅读 · 0 评论