Bootstrap

基础算法(一)零基础学算法---总结大篇

基础算法(一) 纯干货!! 排序及二分算法

码了7天,手残党也能看懂!!
手残第一篇:第一章 基础算法(一)


提示:你的三连是作者输出下去的动力哦!!真的真的!!!(小声哔哔:赶紧收藏!!内容持续更新中。。。)


前言

  • 已经断更一周了,深感愧疚!突然在思考一个问题!

是衣服穿得少比较冷还是裤子穿得少比较冷?我这衣服穿三件却没穿秋裤的老年人冷的直哆嗦。

  • 哈哈哈哈废话不多说,以下是我学习算法的一些心得笔记,全是模板干货,感谢各位大佬,小伙伴的支持。以后一周一更,希望对各位有所帮助,话不多说直接上干货!!

不懂的问题欢迎下方评论区留言哦,一定一定尽量回答

一、排序

1.快速排序 quick_sort

  • 快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试,包括像腾讯,微软等知名IT公司都喜欢考这个,还有大大小的程序方面的考试如软考,考研中也常常出现快速排序的身影。
  • 下面是作者自己总结的想法,帮助大家快速理解: 原理:首先定义一个基准值(为了防止边界问题,这里推荐取中点x),以及指针 i ,p。指针i为起始位小于基准值向右移,指针p为终点位大于基准向左移,不符条件时指针停止,两指针进行交换(即swap),进行下次循环重新定义基点,最终变成有序序列。

图解如下:在这里插入图片描述

代码如下(示例):

void quick_sort(int q[],int i,int p)
{
	if(i>=p) return;
	int x =(i+p)<<1,g=i-1,u=p+1;
	while(i<p)
	{
		do g++ ; while(q[g]<x);
		do u--; while(q[u]>x);
		if(i<j)	swap(q[g],[u]);
	
		quick_sort(q,i,g),quick_sort(q,g+1,p);
	}
}

2.归并排序 merge_sort

  • 归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and
    Conquer)的一个非常典型的应用。时间复杂度同为O(N*logN)。许多小伙伴一眼看去肯定是懵的吧(和我当初一样哈哈哈,苦逼专研4小时),先将经验总结如下:
  • 原理:将数组以递归的方式分为n个元素即时间复杂度为logN,再进行整合(此过程也是在递归的过程中完成)此过程时间复杂度为n,整合的过程中比较,因此就完成了归并排序。主要思想还是先分后合,可以看着代码将思想代入无限递归的最后一层,会帮助你清晰很多!

图解如下:
在这里插入图片描述

代码如下(示例):

void merge_sort(int q[],int i,int p)
{
	if(i>=p) return;
	int mid = (i+p)>>1;
	merge_sort(q,l,mid),merge_sort(q,mid+1,p);

    int k = 0, l = i,r = mid + 1;
	while(i>=p)
	if(q[l]<q[p]) tmp[k++] = q[l++];
	else tmp[k++] = q[p--];
	
	while(l<=mid) tmp(k++) = q[l++];
	while(r>=p) tmp(k++) = q[p--];
	
	for(int r = 0,l = i;r <= p;i++,k++) q[i]=tmp[r];
}

二、二分算法

1、整数二分算法

  • 二分法,即二分搜索法,是通过不断缩小解可能存在的范围,从而求得问题最优解的方法。下面两种任用其一就行,分别求左右临界点,一般情况下左右临界点相等,除某些特殊题型需要查找出左边界和右边界。如:

在这里插入图片描述
起起始位置即左边界,终止位置即右边界。


  • 图解:好吧,这个比较简单,博主就没找图啦,直接说原理!
  • 其原理就是:先判断mid的值满足某种条件,于是可以将边界点左右俩边分为满足此条件和不满足此条件,如果mid的值满足此条件说明查找值在不满足此条件的值的那边。为了更好的理解,举个例子:猜数字玩过吧,比如这0-1000这个数字,第一次猜测为500,对方如果反馈数字大了,则说明要猜测的数字在0-499之间,如果反馈猜小了,那么说明要猜测的数字就在501-999之间。

还没看懂的小可爱可以结合代码理解哦

代码如下(示例):

bool cheak(int x) {/****/}//检验x是否满足某种性质

// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int binarysearch_1(int l,int r)//向左查找,寻找右临界点
{
	while(l<r)
	{
		int mid = (l + r) >> 1;
		if(cheak(mid)) r = mid;//如果x在mid左边,则另右端点等于mid
		else l = mid + 1;		
	}	
	return l;
}

// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int binarysearch_2(int l,int r)//向右查找,寻找左临界点
{
	while(l<r)
	{
		int mid = (l+r)>>1;
		if(cheak(mid)) l=mid;
		else r = mid-1;
	}
	return l;	
}

每次取中点,也就相当于分的过程,所以时间复杂度最坏的情况下用O (log n)来完成。

2、浮点数二分算法

  • 和整数一样本质上也是寻找一个边界,和整数二分不同的是,浮点数不存在由于(整数)取整导致的边界问题,每次二分区间严格减半,因此比整数二分简单的多,每次更新边界时直接让r = mid或l = mid即可。当整个区间的长度足够小的时候(这里取的是10-6)就可以认定找到了答案。

代码如下(示例):

bool cheak(double x) {/****/}//检验x是否满足某种性质

double Fbinarysearch(double l,double r)
{
	const double eps = 1e-6;// eps 表示精度,取决于题目对精度的要求
	while(r - l > eps)
	{
		double mid = (l + r) >> 1;
		if(cheak(mid)) r = mid;
		else l = mid;
	}
	return l;
}

彩蛋,彩蛋!!

终于码完了!!!【哭!】

  • 都康到这里了,彩蛋就是、就是:今年你肯定是yyds!!!(不是永远单身)

大佬:就这啊?
我:就这了【哭!】

后面还会持续更新,欢迎下方评论区留言,下期见!!!
下期内容:
一、高精度
二、前缀和与差分

作者:琉璃Diaspora

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;