《算法笔记》 第四章 入门篇(2)--算法初步

一、排序
①插入排序

#define maxn 10000
int A[maxn],n;
void insertSort()
{
	for(int i=2;i<=n;i++)
	{
		int temp=A[i],j=i;
		while(j>1&&temp<A[j-1])
		{
			A[j]=A[j-1];
			j--;
		}
		A[j]=temp;
	}
}

②利用sort排序,注意sort的重写的排序规则
头文件#include
sort(起始位置地址,结束位置地址,排序规则)
sort(a,a+8,complare);
strcmp(s1,s2);
如果返回值 < 0,则表示 s1 小于 s2。
如果返回值 > 0,则表示 s1 大于 s2。
如果返回值 = 0,则表示 s1 等于 s2。
二、散列hash
空间换时间
开辟一个数组来确定存储查找的次数等信息(对于数据还是有一定的限制,若数据过大,开辟空间过大则不适合使用这个方法,或者也可以设计散列函数)
输入时可以用 char *gets(char *str)
三、二分
①二分查找

//在严格递增的序列里查找元素x 
int binarySearch(int A[],int left,int right,int x)
{
	int mid;
	while(left<=right)
	{
		mid=left+(right-left)/2;
		if(A[mid]==x)
		{
			return mid;
		}
		else if(A[mid]>x)
		//递增序列此处用>,递减序列此处用< 
		{
			right=mid-1;
		}
		else
		{
			left=mid+1;
		}
	}
	return -1;
} 
//求序列中的第一个大于等于x的元素的位置  A为递增序列 
int lower_bound(int A[],int left,int right,int x)
{
	int mid;
	while(left<right)//注意这里没有等号 
	{
		mid=left+(right-left)/2;
		if(A[mid]<=x)
		// 此处>=求的是第一个大于等于x的元素的位置
		//此处<=求的是第一个小于等于x的元素的位置 
		{
			right=mid;
		}		
		else
		{
			left=mid+1;
		}
	}
	return left;
} 
//求递增序列中第一个大于x的元素的位置
int upper_bound(int A[],int left,int right,int x)
{
	int mid;
	while(left<right)//注意这里没有等号 
	{
		mid=left+(right-left)/2;
		if(A[mid]>x)
		// 此处>求的是第一个大于x的元素的位置
		//此处<求的是第一个小于x的元素的位置 
		{
			right=mid;
		}		
		else
		{
			left=mid+1;
		}
	}
	return left;
} 
//解决“寻找有序序列第一个满足某条件的元素的位置”
int solve(int left,int right)
{
	int mid;
	while(left+1<right)
	{
		mid=left+(right-left)/2
		if(/*条件成立*/)
		{
			right=mid;
		}
		else
		{
			left=mid;
		}
	}
	return right;
}

②二分法拓展:求根号二的近似值、半圆储水装置装水问题、木棒切割问题
③快速幂:

//快速幂 a的b次方%m 
typedef long long LL;
LL binaryPow(LL a,LL b,LL c)
{
	if(b==0)
	{
		return 1;
	}
	if(b%2==1)
	{
		return a*binaryPow(a,b-1,m)%m; 
	}
	else
	{
		LL mul = binaryPow(a,b/2,m);
		return mul*mul%m;
	}
}

四、two points
例1:给定一个递增的正整数序列和一个正整数M,求序列中的两个不同位置的数a和b,使得它们的和恰好为M
例二:序列合并问题

//序列合并问题 AB序列均为递增序列,将二者合并为一个递增序列C 
int merge(int A[],int B[],int C[],int n,int m)
{
	int i=0,j=0,index=0;
	while(i<n&&j>m)
	{
		if(A[i]<=B[j])
		{
			C[index++]=A[i++];
		}
		else
		{
			C[index++]=B[j++];
		}
	}
	while(i<n)
	{
		C[index++]=A[i++];
	}
	while(j<m)
	{
		C[index++]=B[j++];
	}
	return index;//返回合并后的总长度 
}

总结题型:使用两个下标志i,j对序列分别进行扫描
利用了数列递增的性质降低了复杂度
快速排序:

//快速排序 
int Partition(int A[],int left,int right)
{
	int temp=A[left];
	while(left<right)
	{
		while(left<right&&A[right]>temp)
		{
			right--;
		}
		A[left]=A[right];
		while(left<right&&A[right]<=temp)
		{
			left++;
		}
		A[right]=A[left];		
	}
	A[left]=temp;
	return left;
} 
void quickSort(int A[],int left,int right)
{
	if(left<right)
	{
		int pos=Partition(A,left,right);
		quickSort(A,left,pos-1);
		quickSort(A,pos+1,right);
	}
} 

生成随机数
头文件:#include<stdlib.h>
#incluude<time.h>
main函数第一句写srand((unsigned)time(NULL));
要输出[a,b]: rand()%(b-a+1)+a
随机选择算法

//从一个无序的数组中求出第K小的数
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <ctime>
#include <cmath>
using namespace std;

//选取随机主元,对区间[left,right]进行划分
int randPartition(int A[],int left,int right)
{
	srand((unsigned)time(NULL));
	int p=(round(1.0*rand()/RAND_MAX*(right-left)+left));
	swap(A[p],A[left]);
	int temp=A[left];
	while(left<right)
	{
		while(left<right&&A[right]>temp)
		{
			right--;
		}
		A[left]=A[right];
		while(left<right&&A[right]<=temp)
		{
			left++;
		}
		A[right]=A[left];		
	}
	A[left]=temp;
	return left;
} 

//随机选择算法,从A[left,right]中返回第K小的数
int randSelect(int A[],int left,int right,int k)
{
	if(left==right)
	{
		return A[left];
	}
	int p=randPartition(A,left,right);
	int M=p-left+1;
	if(k==M)
	{
		return A[p];
	}
	if(k<M)
	{
		return randSelect(A,left,p-1,k);
	}
	else
	{
		return randSelect(A,p+1,right,k-M);
	}
} 

int main()
{
	int A[10]={5,86,35,1,56,2,4,8,64,95};
	for(int i=1;i<=10;i++)
	{
		cout<<randSelect(A,0,9,i)<<endl;
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值