听说了很多的大牛的成长历程都从写自己的博客开始
虽然很久之前就开了博客但是没有坚持下去,从今天开始让自己养成这样的习惯。学着写博客、学着分享。
每天尽量发一篇文章、其他学习文章随着学习进度慢慢写
第一天学习计划:学习算法递归与分支策略,写出二分搜索算法、合并排序算法、快速排序算法
0X00 递归思想:
1、相关概念
直接调用自己或者间接通过一些语句调用自己
一个使用函数自身给出定义的函数叫做递归函数
优点:描述问题自然,证明算法容易
缺点:时间、空间复杂度高
一个递归问题可以分为“回推”和“逆推”两个阶段
2、递归应满足的条件
定义中必须包含一个基本部分,其中对于n的一个或多个值,f(n)必须是直接定义的(也就是必须有递归的出口)
在递归部分中,右侧出现的所有f的参数必须有一个比n小(保证每次递归调用规模减小)
3、经典例题
~Fibonacci数列递归算法
int Fibonacci(int n)
{
if(n <= 1)
return 1;
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
~排列问题的递归算法
/*
*问题描述
*设计一个递归算法生成n个元素{r1,r2,……,rn}的全排列。记为perm({r1,r2,……,rn}).
*解决思路
*设R={r1,r2,……,rn}是要进行排列的n个元素,Ri=R-{ri}。
*/
template<class T>
void Perm(T list[], int k, int m) //生成所有[k:m]的排列方式
{
int i;
if(k == m) //递归出口
{
for(i=0; i <= m; i++)
cout << list[i];
cout << endl;
}
else //递归产生各种排列
{
for(i = k; i <= m; i++)
{ //i=>ri
swap(list[i],list[k]);
Perm(list, k+1, m); //对n-1个元素进行全排列
swap(list[i],list[k]); //排列后为保证无重复结果,将ri换回
}
}
}
0X01 分治法思想
1、基本概念
分治法解决一个大的问题时可以分成多个更小的问题、分别解决每个小问题后将每个小问题的解答组合起来,得到原来大问题的解
分治思想解决问题的代码模型为:
Divide-and-Conquer(P) //P为求解问题的规模
{
if(|P| <= n0) Adhoc(P); //判断规模P是否足够小,即子问题的规模
divide P into smaller subinstances P1,P2,…,Pk;
for(i=1;i<=k;i++)
yi=Divide-and-Conquer(Pi); //分治解决问题
return Merge(y1,…,yk); //合并子问题结果得到最终结果
}
2、经典问题
~二分搜索
/*
*问题描述
*给定已排好序的n个元素,在n个元素中找出一特定元素x,找到则将其位置交给赋值给变量j,否则j=-1
*解决思想
*取中间元素作比较元素,相等则返回,不相等则在相应的位置继续寻找
*/
template<class T>
int binarySearch(T list[], const T& x, int n) //list为排好顺序的数组、x为寻找的元素、n为数组规模
{
int left = 0, right = n-1;
int middle = 0;
while(left <= right)
{
middle = (left + right) / 2;
if(list[middle] == x) return middle;
if(x > list[middle]) left = middle + 1;
else right = middle - 1;
}
return -1;
}
~合并排序——插入法
/*
*问题描述
*已知n个元素的数组list[1:n],将list中元素按不降序排列
*解决思路
*从第二个元素开始取出与之前的第i个元素进行大小对比
*当遇到不小于list[i]的元素时插入list数组
*/
template<class T>
void insertionSort(T list[], int n) //数组list、数组规模n
{
T item;
int i;
for (int j = 1; j < n; j++)
{
item = list[j]; //取出当前元素
i = j - 1;
while (item < list[i] && i>-1)
{
list[i + 1] = list[i];
i--;
}
list[i + 1] = item;
}
}
算法时间复杂度分析:插入算法的while循环中语句执行次数可能为0~j次,因此最坏的时间复杂度为O(n^2),当然,输入之前就是排好顺序的话时间复杂度为最好情况的O(n)
~2、归并排序
void merge(int *data, int start, int end, int *result)
{
int left_length = (end - start + 1) / 2 + 1;//左部分区间的数据元素的个数
int left_index = start;
int right_index = start + left_length;
int result_index = start;
while (left_index < start + left_length && right_index < end + 1)
{
//对分别已经排好序的左区间和右区间进行合并
if (data[left_index] <= data[right_index])
result[result_index++] = data[left_index++];
else
result[result_index++] = data[right_index++];
}
while (left_index < start + left_length)
result[result_index++] = data[left_index++];
while (right_index < end + 1)
result[result_index++] = data[right_index++];
}
void merge_sort(int *data, int start, int end, int *result)
{
if (1 == end - start)//如果区间中只有两个元素,则对这两个元素进行排序
{
if (data[start] > data[end])
{
int temp = data[start];
data[start] = data[end];
data[end] = temp;
}
return;
}
else if (0 == end - start)//如果只有一个元素,则不用排序
return;
else
{
//继续划分子区间,分别对左右子区间进行排序
merge_sort(data, start, (end - start + 1) / 2 + start, result);
merge_sort(data, (end - start + 1) / 2 + start + 1, end, result);
//开始归并已经排好序的start到end之间的数据
merge(data, start, end, result);
//把排序后的区间数据复制到原始数据中去
for (int i = start; i <= end; ++i)
data[i] = result[i];
}
}
~快速排序
void sort(int array[], int left, int right) {
int ltemp = left, rtemp = right;
int f = array[(left + right) / 2];
while (ltemp<rtemp)
{
while (array[ltemp] < f)
{
ltemp++;
}
while (array[rtemp] > f)
{
rtemp--;
}
if (ltemp < rtemp) {
int temp = array[ltemp];
array[ltemp] = array[rtemp];
array[rtemp] = temp;
ltemp++;
rtemp--;
}
}
if (ltemp == rtemp) {
ltemp++;
}
if (left < rtemp) {
sort(array, left, ltemp - 1);
}
if (ltemp < right) {
sort(array, rtemp + 1, right);
}
}
好的问题大概就这样,明天计划学一下python的正则表达式、多线程以及一些其他的算法。
希望自己能坚持下去。