【练习】数据结构和算法复习题
2017-08-27 20:54
369 查看
复习数据结构,写一些简单的题目复习一下。
通常我们的做法是(尤其是在学习阶段):定义一个新的变量,借助它完成交换。代码如下:
int a,b;
a=10; b=15;
int t;
t=a; a=b; b=t;
这种算法易于理解,特别适合帮助初学者了解计算机程序的特点,是赋值语句的经典应用。在实际软件开发当中,此算法简单明了,不会产生歧义,便于程序员之间的交流,一般情况下碰到交换变量值的问题,都应采用此算法(以下称为标准算法)。
上面的算法最大的缺点就是需要借助一个临时变量。那么不借助临时变量可以实现交换吗?答案是肯定的!
1) 算术运算
简单来说,就是通过普通的+和-运算来实现。代码如下:
int a,b;
a=10;b=12;
a=b-a; //a=2;b=12
b=b-a; //a=2;b=10
a=b+a; //a=10;b=10
通过以上运算,a和b中的值就进行了交换。表面上看起来很简单,但是不容易想到,尤其是在习惯标准算法之后。
它的原理是:把a、b看做数轴上的点,围绕两点间的距离来进行计算。
具体过程:第一句“a=b-a”求出ab两点的距离,并且将其保存在a中;第二句“b=b-a”求出a到原点的距离(b到原点的距离与ab两点距离之差),并且将其保存在b中;第三句“a=b+a”求出b到原点的距离(a到原点距离与ab两点距离之和),并且将其保存在a中。完成交换。
此算法与标准算法相比,多了三个计算的过程,但是没
4000
有借助临时变量。(以下称为算术算法)
该算法还可以这样做:
int a,b;
a=10;b=12;
a=a+b=22;
b=a-b=10;
a=a-b=12;
两个减操作一个加操作,执行的先后顺序不一样,其原理也稍微有些区别,但根本原理是一样滴。
3) 位运算
通过异或运算也能实现变量的交换,这也许是最为神奇的,请看以下代码:
int a=10,b=12; //a=1010^b=1100;
a=a^b; //a=0110^b=1100;
b=a^b; //a=0110^b=1010;
a=a^b; //a=1100=12;b=1010;
此算法能够实现是由异或运算的特点决定的,通过异或运算能够使数据中的某些位翻转,其他位不变。这就意味着任意一个数与任意一个给定的值连续异或两次,值不变。
即:a^b^b=a。将a=a^b代入b=a^b则得b=a^b^b=a;同理可以得到a=b^a^a=b;轻松完成交换。
以上三个算法均实现了不借助其他变量来完成两个变量值的交换,相比较而言算术算法和位算法计算量相当,地址算法中计算较复杂,却可以很轻松的实现大类型(比如自定义的类或结构)的交换,而前两种只能进行整形数据的交换(理论上重载“^”运算符,也可以实现任意结构的交换)
假设A上台阶,一次可以跨1层,2层,3层.. 或m层,问A上n层台阶,有多少种走法?
其中,m和n都是正整数,并且 m <= n, m <= 10, n <= 50
请编程解决这个问题,并详细说明解题思路。
解:典型的递归问题。考虑第一步,有三种可能,走一步,走两步,走三步。立马就有一个递归式,f(n) = f(n - 1) + f(n - 2) + f(n - 3)。终结点是f(1) f(2) f(3)。这样有很大重复,可以用一个备忘录记下来这些值。
#include <iostream>
using namespace std;
int mem[1000] = {};
int f(int n)
{
if (mem
!= 0) // 先找记录
return mem
;
if (n <= 0) return 0;
if (n == 1) return 1;
if (n == 2) return 2;
if (n == 3) return 4;
mem
= f(n - 1) + f(n - 2) + f(n - 3);
return mem
;
}
int main()
{
cout << f(10);
}
1. 找出一个字符串中的括号匹配数。
stack#include <stack> #include <iostream> using namespace std; int countMatch(string s) { if(s.size() == 0) return 0; stack<char> count; int n = 0 ; // 记录匹配次数 for(char c: s) { if(c == '(') count.push(c); else if(c == ')') { char t = count.top(); if( t == '(') { count.pop(); n++; } } } return n; } int main() { string s = "int a= (1 + 2()) * (2 - 4) * (3))))()) + 0" ; cout << countMatch(s); } /* 输出: 5 */
2. 计算子字符串匹配的次数
#include<iostream> #include<string> using namespace std; int Match(string longstr,string shortstr) { if(shortstr.size() == 0 || longstr.size() == 0) return 0; string::iterator li = longstr.begin(); string::iterator si = shortstr.begin(); string::iterator ti; int count = 0; while(li != longstr.end()) { ti = li; for(si = shortstr.begin(); ; si++, li++) { if(si == shortstr.end()) { count ++; goto goon; } if(li == longstr.end() || *si != *li) goto skip; } skip: li = ++ti; continue; goon: continue; } return count; } int main() { cout << Match("abcdcfabcsdsda", "dc"); }
3。 不使用第三个数,交换两个整数
题目:a=10,b=15,将a / b的值互换。通常我们的做法是(尤其是在学习阶段):定义一个新的变量,借助它完成交换。代码如下:
int a,b;
a=10; b=15;
int t;
t=a; a=b; b=t;
这种算法易于理解,特别适合帮助初学者了解计算机程序的特点,是赋值语句的经典应用。在实际软件开发当中,此算法简单明了,不会产生歧义,便于程序员之间的交流,一般情况下碰到交换变量值的问题,都应采用此算法(以下称为标准算法)。
上面的算法最大的缺点就是需要借助一个临时变量。那么不借助临时变量可以实现交换吗?答案是肯定的!
1) 算术运算
简单来说,就是通过普通的+和-运算来实现。代码如下:
int a,b;
a=10;b=12;
a=b-a; //a=2;b=12
b=b-a; //a=2;b=10
a=b+a; //a=10;b=10
通过以上运算,a和b中的值就进行了交换。表面上看起来很简单,但是不容易想到,尤其是在习惯标准算法之后。
它的原理是:把a、b看做数轴上的点,围绕两点间的距离来进行计算。
具体过程:第一句“a=b-a”求出ab两点的距离,并且将其保存在a中;第二句“b=b-a”求出a到原点的距离(b到原点的距离与ab两点距离之差),并且将其保存在b中;第三句“a=b+a”求出b到原点的距离(a到原点距离与ab两点距离之和),并且将其保存在a中。完成交换。
此算法与标准算法相比,多了三个计算的过程,但是没
4000
有借助临时变量。(以下称为算术算法)
该算法还可以这样做:
int a,b;
a=10;b=12;
a=a+b=22;
b=a-b=10;
a=a-b=12;
两个减操作一个加操作,执行的先后顺序不一样,其原理也稍微有些区别,但根本原理是一样滴。
3) 位运算
通过异或运算也能实现变量的交换,这也许是最为神奇的,请看以下代码:
int a=10,b=12; //a=1010^b=1100;
a=a^b; //a=0110^b=1100;
b=a^b; //a=0110^b=1010;
a=a^b; //a=1100=12;b=1010;
此算法能够实现是由异或运算的特点决定的,通过异或运算能够使数据中的某些位翻转,其他位不变。这就意味着任意一个数与任意一个给定的值连续异或两次,值不变。
即:a^b^b=a。将a=a^b代入b=a^b则得b=a^b^b=a;同理可以得到a=b^a^a=b;轻松完成交换。
以上三个算法均实现了不借助其他变量来完成两个变量值的交换,相比较而言算术算法和位算法计算量相当,地址算法中计算较复杂,却可以很轻松的实现大类型(比如自定义的类或结构)的交换,而前两种只能进行整形数据的交换(理论上重载“^”运算符,也可以实现任意结构的交换)
4. 台阶问题
假设A上台阶,一次可以跨1层,2层或3层,问A上50层台阶,有多少种走法?假设A上台阶,一次可以跨1层,2层,3层.. 或m层,问A上n层台阶,有多少种走法?
其中,m和n都是正整数,并且 m <= n, m <= 10, n <= 50
请编程解决这个问题,并详细说明解题思路。
解:典型的递归问题。考虑第一步,有三种可能,走一步,走两步,走三步。立马就有一个递归式,f(n) = f(n - 1) + f(n - 2) + f(n - 3)。终结点是f(1) f(2) f(3)。这样有很大重复,可以用一个备忘录记下来这些值。
#include <iostream>
using namespace std;
int mem[1000] = {};
int f(int n)
{
if (mem
!= 0) // 先找记录
return mem
;
if (n <= 0) return 0;
if (n == 1) return 1;
if (n == 2) return 2;
if (n == 3) return 4;
mem
= f(n - 1) + f(n - 2) + f(n - 3);
return mem
;
}
int main()
{
cout << f(10);
}
相关文章推荐
- 算法练习:将字符串中所有的空格替换为'%20'(只用基本数据结构)
- 算法练习:字符串原地逆序(in-place reverse)(只用基本数据结构)
- 数据结构、算法与应用C++语言描述(第二版) 第一章部分练习参考答案
- 数据结构 练习 20-查找 算法
- 【Top】今天开始写关于July的博客的数据结构和算法练习
- Hark的数据结构与算法练习之基数排序
- 算法与数据结构上机练习2
- 对链表的操作(数据结构线性表算法设计练习)
- 2018年全国多校算法寒假训练营练习比赛(第一场) D.N阶汉诺塔变形(数据结构)
- 算法与数据结构第五章树上机练习
- 数据结构及算法练习--树相关
- 算法练习:判断一个字符串中的字符是否唯一(只用基本数据结构)
- 算法练习:检测一个int(整型)数组中是否存在相同的数(只用基本数据结构)
- 算法设计和数据结构学习_3(《数据结构和问题求解》part2笔记)
- 数据结构和算法为什么这么重要?
- 算法练习---斐波那契数列
- [置顶] 【数据结构】算法时间复杂度分析
- 前端学习总结(二十二)——常见数据结构与算法javascript实现
- 数据结构和算法17 之拓扑排序
- 数据结构【栈、队列、串】复习题