第一周总结

前言

第一周学习内容


一、排序算法

1、快速排序

快速排序分为两个过程:

  1. 将数列分成两部分(要求保证相对大小关系);
  2. 递归到两个子序列中并分别进行快速排序;
int partition(int arr[],int low,int high){
	int pivot=arr[high];
	int i=low-1;
	for(int j=low;j<high;j++){
		if(arr[j]<=pivot){
			i++;
			swap(&arr[i],&arr[j]);
			
		}
	}
	swap(&arr[i+1],&arr[high]);
	return i+1;
	
}
void quickSort(int arr[],int low,int high){
	if(low<high){
		int pi=partition(arr,low,high);
		quickSort(arr,low,pi-1);
		quickSort(arr,pi+1,high);
		
		
	}
}

2、归并排序

核心思想:

将两个有序的数组 a[i] 和 b[j] 合并为一个有序数组 c[k]

从左往右枚举 a[i] 和 b[j],找出最小的值并放入数组 c[k];重复上述过程直

到 a[i] 和 b[j] 有一个为空时,将另一个数组剩下的元素放入 c[k]

void merge(int arr[],int left,int mid,int right){
	int n1=mid-left+1;
	int n2=right-mid;
	int L[n1],R[n2];
	for(int i=0;i<n1;i++){
		L[i]=arr[left+i];
		
	}
	for(int j=0;j<n2;j++){
		R[j]=arr[mid+1+j];
		
	}
	int i=0,j=0,k=left;
	while(i<n1&&j<n2){
		if(L[i]<=R[j]){
			arr[k]=L[i];
			i++;
			
		}else{
			arr[k]=R[j];
			j++;
		}
		k++;
	}
	while(i<n1){
		arr[k]=L[i];
		k++;
		i++;
	}
	while(j<n2){
		arr[k]=R[j];
		j++;
		k++;
		
	}
}
void mergeSort(int arr[],int left,int right){
	if(left<right){
		int mid=left+(right-left)/2;
		mergeSort(arr,left,mid);
		mergeSort(arr,mid+1,right);
		merge(arr,left,mid,right);
		
	}
}

二、二分法

在有序数组中,

每次考察数组的中间元素,如果中间元素刚好是要找的,就结束搜索过程;如果中间元素小于所查找的值,则向右侧查找;如果中间元素大于所查找的值则,向左侧查找。

int erfenchazhao(int nums[],int n,int k,int ret){
	int left=0,right=n-1;
	while(left<=right){
		int mid=left+(right-left)/2;
		if(nums[mid]==k){
			if(ret){
				if(mid==0||nums[mid-1]!=k){
					return mid;
				}else{
					right=mid-1;
				}
			}else{
				if(mid==n-1||nums[mid+1]!=k){
					return mid;
				}else{
					left=mid+1;
				}
			}
		}else if(nums[mid]<k){
			left=mid+1;
			
		}else{
			right=mid-1;
		}
	}
	return -1;
}

三、前缀和与差分

差分可以当作是一种求和的逆运算。

1、一维前缀和

sum[i]=sum[i-1]+arr[i]

利用前缀和对矩阵某区间进行加减操作

chafen[x]+=c;

chafen[[y+1]-=c;

2、一维差分

arr[i]=sum[i]-um[i-1]

3、二维前缀和

sum[i][j]=sum[i-1][j]+sum[i][j-1]+arr[i][j]-sum[i-1][j-1]

利用前缀和对矩阵某区间进行加减操作

chafen[x][y]+=c;

chafen[x][h+1]-=c;

chafen[z+1][y]-=c;

chafen[z+1][h+1]+=c;

4、二维差分

arr[i][j]=sum[i][j]-sum[i][j-1]-sum[i-1][j]+sum[i-1][j-1]

四、位运算、离散化、双指针

1、位运算

a、左移和右移

num << i 表示将  的二进制表示向左移动 num 位所得的值。

num >> i 表示将  的二进制表示向右移动 num 位所得的值。

b、按位与、或、异或、取反

&  |   ^   ~

c、求n的第k位数字:

         n >> k & 1

d、返回n的最后一位1:

        lowbit(n) = n & -n

2、离散化

因为数轴是无限长的,直接存储每个位置的值不现实。所以我们可以使用离散化的方法。

离散化就是把无限空间中有限的个体映射到有限的空间中去,以提高算法的时空效率。

        首先,我们把所有操作的位置   和询问的区间端点  、  都收集起来,进行排序去重,这样就得到了一个离散化后的坐标集合。
        代码如下:

vector<int> alls;
sort(alls.begin(),alls.end());
alls.erase(unique(alls.begin(),alls.end),alls.end);

int find(int x){
	int l=0,r=alls.size()-1;
	while(l<r){
		int mid=l+r>>1;
		if(alls[mid]>x){
			r=mid;
		}else{
			l=mid+1;
		}
		
	}
	;return r+1;
}

        然后,对于每个操作,我们在离散化后的坐标集合中找到对应的位置,进行累加操作。
        最后,对于每个询问,我们在离散化后的坐标集合中找到对应的区间,计算这个区间内的累加和。

3、双指针

for(int i=0,j=0;i<n;i++){
	while(j<i&&check(i,j)){
		j++;
		
		
		
	}
}

五、高精度

模拟四则运算

a、高精度加法

void add(int *a,int *b,int *c){
	for(int i=0;i<len-1;i++){
		c[i]+=a[i]+b[i];
		if(c[i]>=10){
			c[i+1]+=1;
			c[i]-=10;
		}
	}
}

vector<int> add(vector<int>&a,vector<int>&b){
	if(a.size()<b.size()){
		return add(b,a);
	}
	vector<int>c;
	int t=0;
	for(int i=0;i<a.size();i++){
		t+=a[i];
		if(i<b.size()){
			t+=b[i];
		}
		c.push_back(t%10);
		t/=10;
	}
	if(t){
		c.push_back(t);
	}
	return c;
}

注:vector a,b,c中数字按照从低位到高位存储。

b、高精度减法

void sub(int *a,int *b,int *c){
	for(int i=0;i<len-1;i++){
		c[i]+=a[i]-b[i];
		if(c[i]<0){
			c[i+1]-=1;
			c[i]+=10;
		}
	}
}

vector<int> sub(vector<int>&a,vector<int>&b){
	int t=0;
	vector<int>c;
	for(int i=0;i<a.size();i++){
		t=a[i]-t;
		if(i<b.size()){
			t-=b[i];
		}
		c.push_back((t+10)%10);
		if(t<0){
			t=1;
		}else{
			t=0;
		}
	}
	while(c.size()>1&&c.back()==0){
		c.pop_back();
	}
	return c;
}

注:vector a,b,c中数字按照从低位到高位存储。

c、高精度乘法

void mul(int *a,int *b,int *c){
	for(int i=0;i<len-1;i++){
		for(int j=0;j<=i;j++){
			c[i]+=a[j]*b[i-j];
			if(c[i]>=10){
				c[i+1]+=c[i]/10;
				c[i]%=10;
			}
		}
	}
}

vector<int> mul(vector<int>&a,int b){
	int t=0;
	vector<int>c;
	for(int i=0;i<a.size()||t;i++){
		if(i<a.size()){
			t+=a[i]*b;
		}
		c.push_back(t%10);
		t/=10;
	}
	while(c.size()>1&&c.back()==0){
		c.pop_back();
	}
	return c;
}

注:vector a,b,c中数字按照从低位到高位存储,默认a>=b>=0。

d、高精度除法

vector<int> div(vector<int>&a,int b,int &r){
	vector<int>c;
	r=0;
	for(int i=0;i<a.size();i++){
		r=r*10+a[i];
		c.push_back(r/b);
		r%=b;
	}
	reverse(c.begin(),c.end());
	while(c.size()>1&&c.back()==0){
		c.pop_back();
	}
	return c;
}

注:vector a,b,c中数字按照从低位到高位存储,默认a>=b,a>=0,b>0。

引用时:

        int r=1;
        c=div(a,b,r);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值