第二章 数组
2.1 寻找最小的K个数
- 快速排序
原地排序,左右分治,选择最后一个为分隔元素,j从后向前,i从前向后,如果j元素值比分隔元素大,就与i位置的元素交换,最后把分隔元素放在中间。
- 线性选择方法
选主元,分割成两部分,分别有a和b个元素。
如果k<=a,必然在a中,如果k=1+a,那么主元是第k小
如果k>a,第k小在b中
这种方法时间会超限,不如sort函数排序更简单
http://codeup.cn/status.php?user_id=Guest
#include<bits/stdc++.h>
using namespace std;
int a[10010];
int getK(int K,int l,int r){
int i=l-1;
for(int j=l;j<=r-1;j++){
if(a[j]<=a[r]){
i++;
swap(a[i],a[j]);
}
}
if(i!=r-1)
swap(a[i+1],a[r]);
if(K-1==i+1){
return a[i+1];
}
else if(K-1<i+1){
return getK(K,l,i);
}
else{
return getK(K,i+2,r);
}
}
int main(){
int n,k;
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
if(k==0)
return 0;
int tempk=getK(1,0,n-1);
cout<<tempk;
for(int i=2;i<=k;i++){
tempk=getK(i,0,n-1);
cout<<" "<<tempk;
}
return 0;
}
2.2 寻找和为定值的两个数
排序,两边夹
#include<bits/stdc++.h>
using namespace std;
int a[100];
int main(){
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
int l=0,r=n-1;
while(l<r){
if(a[l]+a[r]==k){
break;
}
else if(a[l]+a[r]>k){
r--;
}
else{
l++;
}
}
if(l<r)
cout<<a[l]<<" "<<a[r];
return 0;
}
/*
input:
7 15
1 2 4 5 7 11 15
*/
2.3 寻找和为定值的多个数
如果n值较小,可以vector <long long> dp[i][j]
用一个值&1<<i来描述选择这件物品的状态。
如果n较大,可以采用递归的方式记录。
#include<bits/stdc++.h>
using namespace std;
int a[100];
int n,k;
vector <int> out;
void cal(int tn,int sum){
if(tn<=0||sum<=0)
return ;
if(sum==a[tn]){
for(int i=0;i<out.size();i++){
cout<<out[i]<<" ";
}
cout<<a[tn];
cout<<endl;
}
out.push_back(a[tn]);
cal(tn-1,sum-a[tn]);
out.pop_back();
cal(tn-1,sum);
}
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
cal(n,k);
return 0;
}
/*
input:
7 15
1 2 4 5 7 11 15
*/
2.4 最大连续子数组和
动规
#include<bits/stdc++.h>
using namespace std;
int d[100];
int a[100];
int n;
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i+1];
}
d[1]=a[1];
for(int i=2;i<=n;i++){
d[i]=max(d[i-1]+a[i],a[i]);
}
int Max=d[1];
for(int i=2;i<=n;i++){
if(d[i]>Max){
Max=d[i];
}
}
cout<<Max;
return 0;
}
/*
input:
8
1 -2 3 10 -4 7 2 -5
*/
2.5 跳台阶问题
斐波那契数列,写好递推公式即可
2.6 奇偶数排序
奇数位于前半部分,偶数位于后半部分
一头一尾中间移动,或者一前一后扫描
2.7 荷兰国旗
用前中后三个指针,中指针根据不同的类型分别与前后交换
2.8 矩阵乘法
施特拉森算法公式
2.9 完美洗牌算法
长度2n,洗牌后交叉出现
- 位置置换,另开一个数组,算出每个位置O(n)时间完成
- 走环算法,2i mod(2n+1),节省空间