9.15开始
1.
写一个程序, 要求功能:求出用1,2,5这三个数不同个数组合的和为100的组合个数。
如:100个1是一个组合,5个1加19个5是一个组合。。。。 请用C++语言写。
解决方案:
普通方法大家都会:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int main(){ int cnt = 0; for(int i = 0; i <= 100; i ++){ for(int j = 0; j <= 50; j ++){ for(int k = 0; k <= 20; k ++){ if(i + 2 * j + 5 * k == 100) cnt ++; } } } printf("%d\n", cnt); return 0; }
但是这循环是101*51*21次,复杂度大
由题知:假设X为1的个数,Y为2的个数,Z为5的个数,那么满足X+2*Y+5*Z = 100
所以X+5*Z = 100 - 2*Y,很明显X+5*Z是一个偶数,并且Z是<=20的,那么对Z做循环
Z=0, X=100,98,...,0
Z=1,X=95,93,...,1
Z=2,X=90,88,...0
.
.
.
Z=19,X=5,3,1
Z=20,X=0
所以结果只要求出100以内的偶数,95以内的奇数...最后是5以内的奇数再加一次就行了
对于一个奇数N求0到N之间的奇数个数为N/2+1,同样的偶数个数为N/2+1
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int main(){ int sum = 0; for(int i = 0; i <= 100; i += 5){ sum += (100 - i) / 2 + 1; } printf("%d\n", sum); return 0; }
2.
写一个链表,删除一个结构体中指定的结点
解决方案:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <cstdlib> struct stu{ int age; stu *next; }*list; struct stu *creatlist(int n){ stu *h, *p, *s; h = new stu; h->next = NULL; p = h; for(int i = 0; i < n; i ++){ s = new stu; p->next = s; scanf("%d", &s->age); s->next = NULL; p = s; } return h; } void output(stu *s){ s = s->next; while(s != NULL){ printf("%d ", s->age); s = s->next; } puts(""); } void deletelist(stu *h, int age){ stu *p = h; stu *s = h->next; while(s != NULL){ if(s->age == age){ p->next = s->next; s = s->next; } else{ p = p->next; s = s->next; } } } int main(){ int n; scanf("%d", &n); stu *s = creatlist(n); //output(s->next); int age; scanf("%d", &age); deletelist(s, age); output(s); return 0; }
3.
将二叉树的两个孩子换位置,即左变右,右变左。不能用递规
解决方案:
1)根结点入队列
2)取队首元素并出列,并将该元素左右儿子进行交换
3)如果队列不为空则跳到步骤2
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <cstdlib> #include <queue> using namespace std; struct tree{ tree *right; tree *left; }*list; void solve(tree *list){ queue <tree*> Q; Q.push(list); while(!Q.empty()){ tree *tmp = Q.front(); Q.pop(); swap(tmp->right, tmp->left); if(tmp->right != NULL) Q.push(tmp->right); if(tmp->left != NULL) Q.push(tmp->left); } }
4.
38头牛中选出3头跑得最快的,使用一个每次只能供6头比赛的场地,要求用最快的方法
解决方案:
38只取6只一组,6*6,取前3名,得3*6+2=20,用了6次
20只取5只一组,取前3名,得到3*4=12,用了4次
12只分两组取前3名,得3*2=6,用了2次
最后再加1次
累计13次
5.
n从1开始,每个操作可以选择对n加1或者对n加倍。若想获得整数2013,最少需要多少个操作
解决方案:
直接进行计算,奇数减1除2,偶数直接除以2,2013>1006>503>251>125>62>31>15>7>3>1
再反过来计算从1到2013的次数,为18次
6.
如下函数,在32bit系统foo(2^31-3)的值是:
Int foo(int x)
{
Return x&-x;
}
解决方案:
这题是先计算31-3再计算2异或28的,然后进行 x & -x
对于x & -x的含义:返回值为0,表示x=0;返回值为1,表示x为奇数;返回值为其他数,表示x为x与2^64的最大公约数,即二进制中从右到左的第一个1出现的位数
扩展:x & (x-1) 表示x进进制中1的个数,每执行一次x = x&(x-1),会将x用二进制表示时最右边的一个1变为0,因为x-1将会将该位(x用二进制表示时最右边的一个1)变为0
所以可通过这个求得一个数是不是2的n次方,代码如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int func(int x) { if( (x&(x-1)) == 0 ) return 1; else return 0; } int main() { int x = 8; printf("%d\n", func(x)); }
7.
给两个单向链表,求是否有公共节点并求该公共节点,要求使用空间最小算法
解决方案:
将链表A遍历以及链表B遍历,分别保存最后一个节点以及他们长度,若相同再证明有公共节点
如果他们长度相等,依次遍历就行,如果长度不等,将长度长的先遍历|len_a - len_b|(表示绝对值)
如图
9.
static静态在申请的时候不分配内存
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
struct A{ A() {} ~A() {} int m1; int m2; }; struct B{ B() {} ~B() {} int m1; char m2; static char m3; }; struct C{ C() {} virtual~C() {} int m1; short m2; }; int main(){ printf("%d %d %d\n", sizeof A, sizeof B, sizeof C); return 0; }
输出的是:8 8 12
10.
定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数min、push以及pop的时间复杂度都是O(1)
解决方案:这题难点在于pop一个元素之后,怎样确定栈中的最小元素,然后查找就要遍历显示不行,
那么就设定一个辅助栈,将每次数据栈中最小的元素依次入栈,见代码(考虑整型)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> using namespace std; class Stack { public: void push(int num){ data_stack.push(num); if(!min_stack.size()) min_stack.push(num); else if(num <= min_stack.top()) min_stack.push(num); } void pop(){ if(data_stack.top() == min_stack.top()) min_stack.pop(); data_stack.pop(); } void output(){ printf("%d\n", min_stack.top()); } protected: private: stack <int > data_stack; stack <int > min_stack; }; int main(){ Stack s; s.push(3); s.output(); s.push(4); s.output(); s.push(2); s.output(); s.push(1); s.output(); s.pop(); s.output(); s.pop(); s.output(); s.push(0); s.output(); return 0; }
11.
求最大子和段
解决方案:从第一个数开始加,如果碰到和为负数则置0,否则和max值比较取最大值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> using namespace std; int a[8] = {1, -2, 3, 10, -4, 7, 2, -5}; int main(){ int sum = a[0], max = a[0]; for(int i = 1; i < 8; i ++){ if(sum + a[i] < 0) sum = 0; else sum += a[i]; if(max < sum) max = sum; } printf("%d\n", max); return 0; }
12.
查找最小的k个元素
解决方案:
朴素方案或者遍历选择最小K个或者快速排序选择前K个,复杂度略高
可以先插入K个到数组中,然后每插入一个数和前K个比较,比最大的小才插入并删除最大的
如何做到在K个当中查找最大的,可以用一个最大堆,或者用第10题两个栈的做法(个人认为可以,只是弹栈的要换一种方式了)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> using namespace std; multiset <int > m; int main(){ m.clear(); m.insert(3); m.insert(5); m.insert(4); m.insert(1); m.insert(7); m.insert(8); m.insert(2); m.insert(6); for(multiset<int > :: iterator it= m.begin(); it != m.end(); it ++){ cout<<*it<<endl; } return 0; }
参考别人的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> using namespace std; const int k = 5; const int maxn = 1000; int max_heap[k + 1]; int ed, maxpos; void insert_min_heap(int data){ int child = 0; if(ed == k + 1){ if(data >= max_heap[1]) return; max_heap[1] = data; for(int i = 1; i * 2 <= k; i = child){ child = 2 * i; if((i * 2 + 1 <= k && max_heap[i*2] < max_heap[i*2+1])){ child ++; } if(max_heap[i] < max_heap[child]) swap(max_heap[i], max_heap[child]); else break; } return; } max_heap[ed ++] = data; for(int i = ed - 1; i > 1; i /= 2){ if(max_heap[i] > max_heap[i/2]) swap(max_heap[i], max_heap[i/2]); else break; } } int main(){ int n, data; ed = 1; while(~scanf("%d", &data)){ insert_min_heap(data); } for(int i = 1; i <= k; i ++) printf("%d ", max_heap[i]); puts(""); return 0; }
13.
写一个堆排序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> using namespace std; int n, a[100]; void init_heap(){ for(int i = n; i; i --){ int cur = i; while(true){ int next = -1; if((cur * 2 <= n) && (next < 0 || a[cur*2] > a[next])) next = cur * 2; if((cur * 2 + 1 <= n) && (a[cur*2+1] > a[next])) next = cur * 2 + 1; if(next < 0 || a[next] <= a[cur]) break; else{ swap(a[cur], a[next]); cur = next; } } } } void heap_sort(){ for(int i = n; i > 1; i --){ swap(a[1], a[i]); int cur = 1; while(true){ int next = -1; if((cur * 2 < i) && (next < 0 || a[cur*2] > a[next])) next = cur * 2; if((cur * 2 + 1 < i) && (a[cur*2+1] > a[next])) next = cur * 2 + 1; if(next < 0 || a[next] <= a[cur]) break; else{ swap(a[cur], a[next]); cur = next; } } } } int main(){ scanf("%d\n", &n); for(int i = 1; i <= n; i ++) scanf("%d", a + i); init_heap(); heap_sort(); for(int i = 1; i <= n; i ++){ printf("%d%c", a[i], i < n ? ' ' : '\n'); } }
14.
前序中序后序遍历,创建二叉树时采用队列实现层序遍历创建
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; struct Node{ int num; Node *l, *r; }; queue <Node * > Q; void creat_tree(Node *p, int num, int &f){ Node *s = new Node; s->num = num; s->l = s->r = NULL; if(f == 1){ p->l = s; f = 2; Q.push(s); return; } p->r = s; f = 1; Q.push(s); Q.pop(); } void dlr_output(Node *p){ if(p == NULL) return; printf("%d ", p->num); dlr_output(p->l); dlr_output(p->r); } void ldr_output(Node *p){ if(p == NULL) return; ldr_output(p->l); printf("%d ", p->num); ldr_output(p->r); } void lrd_output(Node *p){ if(p == NULL) return; lrd_output(p->l); lrd_output(p->r); printf("%d ", p->num); } int main(){ Node *root = new Node; Node *p = new Node; int f = 0; int num; while(!Q.empty()) Q.pop();//清空队列 while(~scanf("%d", &num)){ if(f == 0){ root->num = num; root->l = NULL; root->r = NULL; f = 1; p = root; Q.push(p); continue; } p = Q.front(); creat_tree(p, num, f); } dlr_output(root);puts(""); ldr_output(root);puts(""); lrd_output(root);puts(""); return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <string> #include <queue> using namespace std; struct TreeNode{ int value; TreeNode *left; TreeNode *right; }; TreeNode *creatTreeNode(int m){ TreeNode *node = new TreeNode; node->value = m; node->right = node->left = NULL; return node; } void DestroyTree(TreeNode *root){ if(root != NULL){ TreeNode *l = root->left; TreeNode *r = root->right; delete root; root = NULL; DestroyTree(l); DestroyTree(r); } } void connectTree(TreeNode *root, TreeNode *l, TreeNode *r){ if(root != NULL){ root->left = l; root->right = r; } } void solve(TreeNode *root); int main(){ TreeNode *node1 = creatTreeNode(1); TreeNode *node2 = creatTreeNode(2); TreeNode *node3 = creatTreeNode(3); TreeNode *node4 = creatTreeNode(4); TreeNode *node5 = creatTreeNode(5); TreeNode *node6 = creatTreeNode(6); TreeNode *node7 = creatTreeNode(7); connectTree(node1, node2, node3); connectTree(node2, node4, node5); connectTree(node3, node6, node7); solve(node1); //DestroyTree(node1); return 0; } void dlr(TreeNode *root){ if(!root) return; stack <TreeNode* > sta; TreeNode *tmp = root; while(tmp != NULL || !sta.empty()){ while(tmp != NULL){ printf("%d ", tmp->value); sta.push(tmp); tmp = tmp->left; } if(!sta.empty()){ tmp = sta.top(); sta.pop(); tmp = tmp->right; } } puts(""); } void ldr(TreeNode *root){ if(!root) return; stack <TreeNode* > sta; TreeNode *tmp = root; while(tmp != NULL || !sta.empty()){ while(tmp != NULL){ sta.push(tmp); tmp = tmp->left; } if(!sta.empty()){ tmp = sta.top(); sta.pop(); printf("%d ", tmp->value); tmp = tmp->right; } } puts(""); } void lrd(TreeNode *root){ if(!root) return; stack <TreeNode* > sta; TreeNode *cur, *pre = NULL; sta.push(root); while(!sta.empty()){ cur = sta.top(); if( (cur->left == NULL && cur->right ==NULL) || (pre != NULL && (pre == cur->left || pre == cur->right))){ printf("%d ", cur->value); sta.pop(); pre = cur; }else{ if(cur->right != NULL) sta.push(cur->right); if(cur->left != NULL) sta.push(cur->left); } } puts(""); } void solve(TreeNode *root){ dlr(root); ldr(root); lrd(root); }
15.
查找链表中倒数第k个结点
解决方案:
设置两个指针,开始指向头结点,然后第一个移动并计数,当移动了k-1次另一指针开始移动,复杂度为o(n)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; struct Node{ int num; Node *next; }; Node *insert(Node *p, int num){ Node *s = new Node; s->num = num; s->next = NULL; p->next = s; return s; } int main(){ int num; Node *root = new Node; Node *p = root; int k; scanf("%d", &k); while(~scanf("%d", &num)){ p = insert(p, num); } int cnt = 0; Node *s1 = root; Node *s2 = root; while(s1 != NULL){ cnt ++; if(cnt >= k + 1){ s2 = s2->next; } s1 = s1->next; } printf("%d\n", s2->num); return 0; }
16.
在排序数组中查找和为给定值的两个数字
解决方案:
确定第一个和最后一个的和,假如相加大于给定的数,则较大数前移,小于则较小数后移,相等就输出
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; int a[100]; int main(){ int n; while(~scanf("%d", &n)){ for(int i = 0; i < n; i ++) scanf("%d", a + i); int num; scanf("%d", &num); int st = 0, ed = n - 1; while(true){ if(a[st] + a[ed] == num){ printf("%d %d\n", a[st], a[ed]); break; }else if(a[st] + a[ed] > num) ed --; else st ++; } } return 0; }
17.
O(logn)求Fibonacci数列
解决方案:
(转)
下面介绍一种时间复杂度是O(logn)的方法。在介绍这种方法之前,先介绍一个数学公式:
{f(n), f(n-1), f(n-1), f(n-2)} ={1, 1, 1,0}n-1
(注:{f(n+1), f(n), f(n), f(n-1)}表示一个矩阵。在矩阵中第一行第一列是f(n+1),第一行第二列是f(n),第二行第一列是f(n),第二行第二列是f(n-1)。)
有了这个公式,要求得f(n),我们只需要求得矩阵{1, 1, 1,0}的n-1次方,因为矩阵{1, 1, 1,0}的n-1次方的结果的第一行第一列就是f(n)。这个数学公式用数学归纳法不难证明。感兴趣的朋友不妨自己证明一下。
现在的问题转换为求矩阵{1, 1, 1, 0}的乘方。如果简单第从0开始循环,n次方将需要n次运算,并不比前面的方法要快。但我们可以考虑乘方的如下性质:
/ an/2*an/2 n为偶数时
an=
\ a(n-1)/2*a(n-1)/2 n为奇数时
要求得n次方,我们先求得n/2次方,再把n/2的结果平方一下。如果把求n次方的问题看成一个大问题,把求n/2看成一个较小的问题。这种把大问题分解成一个或多个小问题的思路我们称之为分治法。这样求n次方就只需要logn次运算了。
实现这种方式时,首先需要定义一个2×2的矩阵,并且定义好矩阵的乘法以及乘方运算。当这些运算定义好了之后,剩下的事情就变得非常简单。完整的实现代码如下所示。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; struct matrix2by2{ matrix2by2( long long m00 = 0, long long m01 = 0, long long m10 = 0, long long m11 = 0 ) :m_00(m00), m_01(m01), m_10(m10), m_11(m11){} long long m_00; long long m_01; long long m_10; long long m_11; }; matrix2by2 matrixmultiply(const matrix2by2 &a, const matrix2by2 &b){ return matrix2by2( a.m_00 * b.m_00 + a.m_01 * b.m_10, a.m_00 * b.m_01 + a.m_01 * b.m_11, a.m_10 * b.m_00 + a.m_11 * b.m_10, a.m_10 * b.m_01 + a.m_11 * b.m_11 ); } matrix2by2 matrixpower(int n){ matrix2by2 matrix; if(n == 1) matrix = matrix2by2(1, 1, 1, 0); else if(n % 2 == 0){ matrix = matrixpower(n/2); matrix = matrixmultiply(matrix, matrix); } else if(n % 2 == 1){ matrix = matrixpower((n-1)/2); matrix = matrixmultiply(matrix, matrix); matrix = matrixmultiply(matrix, matrix2by2(1, 1, 1, 0)); } return matrix; } int main(){ printf("%d\n", matrixpower(10-1).m_00); return 0; }
18.
定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。如把字符串abcdef左旋转2位得到字符串cdefab。请实现字符串左旋转的函数。要求时间对长度为n的字符串操作的复杂度为O(n),辅助内存为O(1)。
解决方案:
假设这字符串简化为XY,刚分三次操作即可,X旋转,Y旋转,XY旋转
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; char s[] = "12345"; int n = 5; int k = 2; void reversestring(char *st, char *ed){ while(st < ed){ char tmp = *st; *st = *ed; *ed = tmp; st ++; ed --; } } int main(){ char *pst1 = s; char *ped1 = s + k - 1; char *pst2 = s + k; char *ped2 = s + n - 1; reversestring(pst1, ped1); reversestring(pst2, ped2); reversestring(pst1, ped2); printf("%s\n", s); return 0; }
19.
解决方案:从右上角开始查找,如果大就消除该列,如果小就消除该行
(修改)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; bool find(int *a, int rows, int cols, int num){ int row = 0; int col = cols - 1; // printf("%d %d %d\n", a[0], num, a[rows * cols - 1]); for(int i = 0; i < rows; i ++){ for(int j = 0; j < cols; j ++){ // printf("%d ", a[i * cols + j]); } // puts(""); } if(a[0] > num || a[rows * cols - 1] < num) return false; //puts("asdf"); while(row < rows && col >= 0){ if(a[row * cols + col] == num) return true; if(a[row * cols + col] > num) col --; else row ++; } return false; } void test(){ int a[][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}}; bool ans = find((int*)a, 4, 4, 15); if( ans ) puts("yes"); else puts("no"); } int main(){ test(); return 0; }
20.
旋转数组二分查找
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; int a[111]; void solve(int st, int ed, int num){ int index1 = st, index2 = ed, mid = st; while(index1 <= index2){ int mid = index1 + index2 >> 1; if(a[mid] == num){ puts("yes"); return; } if(a[mid] >= a[st]){ if(num < a[mid] && num >= a[index1]) index2 = mid - 1; else index1 = mid + 1; }else{ if(num > a[mid] && num <= a[index2]) index1 = mid + 1; else index2 = mid - 1; } } puts("no"); } int main(){ int n; scanf("%d", &n); for(int i = 0; i < n; i ++) scanf("%d", a + i); int num; scanf("%d", &num); solve(0, n - 1, num); return 0; }
21.
给一个数,打印从1到这个数位数的最大数字
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; void PrintNum(char *num){ int len = strlen(num); bool f = 1; for(int i = 0; i < len; i ++){ if(f && num[i] == '0') continue; else f = 0; putchar(num[i]); } printf("\t"); } bool Increment(char *num){ bool isOverflow = false; int nTakeover = 0; int len = strlen(num); for(int i = len - 1; i >= 0; i --){ int sum = num[i] - '0' + nTakeover; if(i == len - 1) sum ++; if(sum >= 10){ if(i == 0) isOverflow = true; else{ sum -= 10; nTakeover = 1; num[i] = '0' + sum; } }else{ num[i] = '0' + sum; break; } } return isOverflow; } int main(){ int n; scanf("%d", &n); char *num = new char [n + 1]; memset(num, '0', n); num[n] = '\0'; while(!Increment(num)){ PrintNum(num); } delete [] num; return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; void PrintNum(char *num){ int len = strlen(num); bool f = 1; for(int i = 0; i < len; i ++){ if(f && num[i] == '0') continue; else f = 0; putchar(num[i]); } printf("\t"); } void f(char *num, int len, int index){ if(index == len - 1){ PrintNum(num); return; } for(int i = 0; i < 10; i ++){ num[index + 1] = i + 48; f(num, len, index+1); } } int main(){ int n; scanf("%d", &n); char *num = new char [n + 1]; memset(num, '0', n); num[n] = '\0'; for(int i = 0; i < 10; i ++){ num[0] = i + 48; f(num, n, 0); } delete [] num; return 0; }
22.
判断一棵树是不是平衡二叉树
解决方案:要想知道是不是平衡二叉树,就得先知道该点左右孩子深度之差,超过二就不是 了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; struct TreeNode{ int value; TreeNode *left; TreeNode *right; }; TreeNode *creatTreeNode(int m){ TreeNode *node = new TreeNode; node->value = m; node->right = node->left = NULL; return node; } void DestroyTree(TreeNode *root){ if(root != NULL){ TreeNode *l = root->left; TreeNode *r = root->right; delete root; root = NULL; DestroyTree(l); DestroyTree(r); } } void connectTree(TreeNode *root, TreeNode *l, TreeNode *r){ if(root != NULL){ root->left = l; root->right = r; } } bool fun(TreeNode *root, int &depth){ if(root == NULL){ depth = 0; return true; } int l_depth, r_depth; if(fun(root->left, l_depth) && fun(root->right, r_depth)){ int diff = l_depth - r_depth; if(diff <= 1 && diff >= -1){ depth = 1 + (l_depth > r_depth ? l_depth : r_depth); return true; } } return false; } int main(){ TreeNode *node1 = creatTreeNode(1); TreeNode *node2 = creatTreeNode(2); TreeNode *node3 = creatTreeNode(3); TreeNode *node4 = creatTreeNode(4); TreeNode *node5 = creatTreeNode(5); TreeNode *node6 = creatTreeNode(6); TreeNode *node7 = creatTreeNode(7); connectTree(node1, node2, node3); connectTree(node2, node4, node5); connectTree(node3, node7, node6); //connectTree(node5, node7, NULL); int depth = 0; if(fun(node1, depth)) puts("yes"); else puts("no"); printf("%d\n", depth); DestroyTree(node1); return 0; }
23.
统计一个排序数组中某一数字出现的次数
解决方案:两次二分查找,第一次查询该数字最左边位置,第二次最右边,因为连续,所以差值+1就是该数字个数了
二分查找时,要稍微处理下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; int a[8] = {1,3,3,3,3,3,3,7}; int len = 8; int getFirstK(int l, int r, int k){ //int l = 0, r = len - 1; if(l > r) return -1; int mid = l + r >> 1; if(a[mid] == k){ if((mid && a[mid - 1] != k) || mid == 0) return mid; else r = mid - 1; }else if(a[mid] < k) l = mid + 1; else r = mid - 1; return getFirstK(l, r, k); } int getLastK(int l, int r, int k){ //int l = 0, r = len - 1; if(l > r) return -1; int mid = l + r >> 1; if(a[mid] == k){ if((mid != len - 1 && a[mid + 1] != k) || mid == len - 1) return mid; else l = mid + 1; }else if(a[mid] < k) l = mid + 1; else r = mid - 1; return getLastK(l, r, k); } int main(){ int first = getFirstK(0, len-1, 2); int last = getLastK(0, len-1, 2); if(first > -1 && last > -1) printf("%d\n", last - first + 1); else puts("no"); return 0; }
24.
一个整型数组里除了两个数字之外,其他的数字都出现了两次,求这两个数字。时间O(n),空间O(1)
解决方案:异或所有元素,求最右边的1,然后按这情况将数组分为两组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; int a[8] = {2,4,3,6,3,2,5,5}; int len = 8; bool is_ok(int num, int cnt){ num = num >> cnt; return (num & 1); } int main(){ int res = 0; for(int i = 0; i < len; i ++) res ^= a[i]; int cnt = 0; while((res & 1) == 0 && cnt < 32){ res = res >> 1; cnt ++; } int ans1 = 0, ans2 = 0; for(int i = 0; i < len; i ++){ if(is_ok(a[i], cnt)) ans1 ^= a[i]; else ans2 ^= a[i]; } printf("%d %d\n", ans1, ans2); return 0; }
25.
输入一个正整数,打印出所有和为该数的正数序列
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; void printf_n(int l, int r){ for(int i = l; i < r; i ++){ printf("%d ", i); } printf("%d\n", r); } void solve(int n){ int l = 1, r = 2; if(n < 3) return; int mid = 1 + n >> 1; int sum = l + r; while( l < mid){ if(sum == n) printf_n(l, r); while(l < mid && sum > n){ sum -= l; l ++; if(sum == n) printf_n(l, r); } r ++; sum += r; } } int main(){ int n; scanf("%d", &n); solve(n); return 0; }
26.
二叉搜索树不创建新的结点转换成双向链表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; struct TreeNode{ int value; TreeNode *left; TreeNode *right; }; TreeNode *creatTreeNode(int m){ TreeNode *node = new TreeNode; node->value = m; node->right = node->left = NULL; return node; } void DestroyTree(TreeNode *root){ if(root != NULL){ TreeNode *l = root->left; TreeNode *r = root->right; delete root; root = NULL; DestroyTree(l); DestroyTree(r); } } void connectTree(TreeNode *root, TreeNode *l, TreeNode *r){ if(root != NULL){ root->left = l; root->right = r; } } void covertToDoubleList(TreeNode **head, TreeNode **list, TreeNode *root){ //TreeNode *root = tt; root->left = *list; if(NULL != *list) (*list)->right = root; else (*head) = root; (*list) = root; printf("%d ", root->value); } void fun(TreeNode **head, TreeNode **list, TreeNode *root){ if(NULL == root) return; if(NULL != root->left) fun(head, list, root->left); covertToDoubleList(head, list, root); /* root->left = *list; if(NULL != *list) (*list)->right = root; else (*head) = root; (*list) = root; printf("%d ", root->value); */ if(NULL != root->right) fun(head, list, root->right); } void solve(TreeNode *root){ TreeNode *head = new TreeNode(); TreeNode *list = new TreeNode(); head = list = NULL; //if(head == NULL)puts("adsf"); fun(&head, &list, root); puts(""); TreeNode *p = head; while(p != NULL){ printf("%d ", p->value); p = p->right; } puts(""); } int main(){ TreeNode *node1 = creatTreeNode(10); TreeNode *node2 = creatTreeNode(6); TreeNode *node3 = creatTreeNode(14); TreeNode *node4 = creatTreeNode(4); TreeNode *node5 = creatTreeNode(8); TreeNode *node6 = creatTreeNode(12); TreeNode *node7 = creatTreeNode(16); connectTree(node1, node2, node3); connectTree(node2, node4, node5); connectTree(node3, node6, node7); solve(node1); //DestroyTree(node1); return 0; }
27.
找出数组中次数超过一半的数字
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; int a[9] = {1,2,2,3,2,2,5,4,2}; int len = 9; bool check(int num){ int cnt = 0; for(int i = 0; i < len; i ++) if(a[i] == num) cnt ++; if(cnt * 2 <= len) return false; else return true; } void solve(){ int res = a[0]; int cnt = 1; for(int i = 1; i < len; i ++){ if(cnt == 0){ res = a[i]; cnt ++; }else if(a[i] == res) cnt ++; else cnt --; } if(check(res)) puts("yes"); else puts("no"); } int main(){ solve(); return 0; }
28.
给定一个整数,求从1到这整数十进制中1出现的次数
解决方案:
分析(转)
简单的方法就是按照给位进行分析
在个位出现1的个数=n/10+(个位=0,0;个位>1,1;个位=1,低0位+1);
十位位出现1的个数=n/100*10+(十位=0,0;十位>1,10,;十位=1,低一位+1);
百位出现1的个数=n/1000*100+(百位=0,0;百位>1,100;百位=1,低两位+1);
等等
算法的复杂度仅仅和位数有关
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <queue> using namespace std; int f(int a){ if(a == 0) return 1; int num = 1; for(int i = 1; i <= a; i ++) num *= 10; return num; } int solve(int n){ int tmp = n; int len = 0; while(tmp){ tmp /= 10; len ++; } tmp = n; int sum = 0; for(int i = 1; i <= len; i ++){ sum += tmp / f(i) * f(i-1); int t = n / f(i-1) % 10; if(t == 1) sum += n % f(i-1) + 1; else if(t > 1) sum += f(i-1); } return sum; } int main(){ int n; scanf("%d", &n); int t = solve(n); printf("%d\n", t); return 0; }
29.
把数组排成最小的数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <string> #include <queue> using namespace std; int a[3] = {3,32,321}; const int len = 3; int cmp(const string &s1, const string &s2){ string ss1 = s1 + s2; string ss2 = s2 + s1; return s1 > s2; } int main(){ char s[len+1][10]; string ss[len]; for(int i = 0; i < len; i ++){ sprintf(s[i], "%d", a[i]); ss[i] = s[i]; } sort(ss,ss + len, cmp); for(int i = 0; i < len; i ++) //printf("%s", s[i]); cout<<ss[i]; puts(""); return 0; }
30.
寻找丑数(只包含因子为2 3 5的数)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <string> #include <queue> using namespace std; int Min(int a, int b, int c){ int x = a < b ? a: b; x = x < c ? x : c; return x; } int getUgly(int n){ if(n <= 0) return 0; int *ugly = new int[n]; ugly[0] = 1; int cnt = 1; int *m2 = ugly; int *m3 = ugly; int *m5 = ugly; while(cnt < n){ int min = Min(*m2 * 2, *m3 * 3, *m5 * 5); ugly[cnt] = min; while(*m2 * 2 <= ugly[cnt]) m2 ++; while(*m3 * 3 <= ugly[cnt]) m3 ++; while(*m5 * 5 <= ugly[cnt]) m5 ++; cnt ++; } int ans = ugly[n - 1]; delete [] ugly; return ans; } int main(){ int n; scanf("%d", &n); int t = getUgly(n); printf("%d\n", t); return 0; }
31.
在字符串中找出第一个只出现一次的字符
解决方案:
先遍历一次建立hash表,然后查找就行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <string> #include <queue> using namespace std; int main(){ char s[333]; scanf("%s", s); int hashmap[270]; memset(hashmap, 0, sizeof hashmap); for(int i = 0; s[i]; i ++) hashmap[s[i]] ++; bool f = true; for(int i = 0; s[i]; i ++){ if(hashmap[s[i]] == 1){ printf("%c\n", s[i]); f = false; break; } } if(f) puts("not found"); return 0; }
32.
判断一个序列是不是某二叉排序树(二叉搜索树,二元查找树)的后序遍历序列
解决方案:
最后一个结点必为根结点,然后根据二叉排序树的性质找到它的左右孩子,然后再递归查找
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <string> #include <queue> using namespace std; bool check(int *a, int n){ if(a == NULL || n < 1) return false; int root = a[n-1]; int l = 0; for(; l < n - 1; l ++){ if(a[l] > root) break; } int r = l; for(; r < n - 1; r ++) if(a[r] < root) return false; bool left = true; if(l > 0) left = check(a, l); bool right = true; if(r < n - 1) right = check(a+l, n - l + 1); return (left && right); } int main(){ int n; scanf("%d", &n); int *a = new int[n]; for(int i = 0; i < n; i ++){ scanf("%d", a + i); } bool ans = check(a, n); if(ans) puts("yes"); else puts("no"); return 0; }
33.
约瑟夫环问题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <string> #include <queue> using namespace std; int main(){ int n; scanf("%d", &n); int m; scanf("%d", &m); int last = 0; for(int i = 2; i <= n; i ++) last = (last + m) % i; printf("%d\n", last); return 0; }
34.
输入两个整数n和m,从数列1,2.......n中随意取几个数,使其和等于m,要求将其中所有的可能组合列出来
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <string> #include <queue> using namespace std; void solve(int n, int m){ if(n < 1 || m < 1) return; if(n > m) n = m; int maxn = 1 << n; for(int i = 1; i < maxn; i ++){ int sum = 0; for(int j = i, k = 1; j; j >>= 1, k ++) if(j&1) sum += k; if(sum == m){ for(int j = i, k = 1; j; j >>= 1, k ++) if(j&1) printf("%d ", k); puts(""); } } } int main(){ int n, m; scanf("%d%d", &n, &m); solve(n, m); return 0; }
35.
将一个整数以字符串输出
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <string> #include <queue> using namespace std; char *int2str(int n){ char *s = new char; char *p = s; bool f = true; if(n == 0){ *p ++ = '0'; *p ++ = '\0'; return s; }else if(n < 0){ f = false; n = - n; } int len = 0; while(n){ *p ++ = n % 10 + 48; n /= 10; ++ len; } if(!f){ len ++; *p ++ = '-'; } *p ++ = '\0'; //printf("%d %s\n\n", len, s); for(int i = 0; i < len / 2; i ++){ char c = s[i]; s[i] = s[len - i - 1]; s[len - i - 1] = c; } return s; } int main(){ int n; scanf("%d", &n); char *s = int2str(n); printf("%s\n", s); return 0; }
36.
求两个字符串的最长连续公共子串并返回分别在两个子串中的位置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <stack> #include <set> #include <algorithm> #include <iostream> #include <string> #include <queue> using namespace std; char *lcs(int &index1, int &index2, char *s1, char *s2){ int mat[111][111]; memset(mat, 0, sizeof mat); int maxlen = 0; for(int i = 0; s1[i]; i ++){ for(int j = 0; s2[j]; j ++){ if(s1[i] == s2[j]){ if(i && j){ mat[i][j] = mat[i-1][j-1] + 1; } else mat[i][j] = 1; if(mat[i][j] > maxlen){ maxlen = mat[i][j]; index1 = i; index2 = j; } } } } char *s = new char[maxlen+1]; for(int i = 0; i < maxlen; i ++){ s[i] = s1[index1 - maxlen + i + 1]; } index1 = index1 - maxlen + 1; index2 = index2 - maxlen + 1; s[maxlen] = '\0'; return s; } int main(){ char s1[111], s2[111]; while(~scanf("%s%s", s1, s2)){ int index1, index2; char *s = lcs(index1, index2, s1, s2); printf("%s %d %d\n", s, index1, index2); } return 0; }
posted @ 2013-09-21 07:16 louzhang_swk 阅读(2346) 评论(2) 推荐(0) 编辑