目录
旋转数组
旋转数组找最小值
旋转数组找指定值
严格递增序列
递增序列
旋转序列找中位数:
旋转数组
旋转数组找最小值
思路
#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=100001;int n,num[N];
int bis(int a[],int left,int right,int n)
{
while(left<right)
{int mid=left+(right-left)/2;
if(a[mid]>a[n-1]) left=mid+1;
else right=mid;
}
return a[left];
}int main()
{scanf("%d",&n);for(int i=0;i<n;i++) scanf("%d",&num[i]);printf("%d",bis(num,0,n-1,n));
}
旋转数组找指定值
严格递增序列
#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=100001;int n,num[N];
int bis(int a[],int left,int right,int n,int x)
{
if (x==a[n-1]) return n-1;
if(x<a[n-1])
{
while(left<right)
{int mid=left+(right-left)/2;
if(a[mid]>a[n-1] || a[mid]<x) left=mid+1;
if(a[mid]>x && a[mid]<a[n-1] ) right=mid-1;
if(a[mid]==x) return mid;
}
return a[left]==x?left:-1;
}
if(x>a[n-1])
{
while(left<right)
{int mid=left+(right-left)/2;
if(a[mid]>a[n-1] && a[mid]<x) {left=mid+1;}
if(a[mid]>x || a[mid]<a[n-1] ) {right=mid-1;}
if(a[mid]==x) {return mid;}}
return a[left]==x?left:-1;
}
}int main()
{scanf("%d",&n);int x;scanf("%d",&x);for(int i=0;i<n;i++) scanf("%d",&num[i]); printf("%d",bis(num,0,n-1,n,x));
}
递增序列
也就是可能有相同值
#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=100001;int n,num[N];
int bis(int a[],int left,int right,int n,int x)
{
if (x==a[n-1]) //return n-1;
{if (a[0]==a[n-1]) return 0;
else for(int i=n-1;i>0;i--) if(a[i-1]!=x && a[i]==x) return i;
}
if(x<a[n-1])
{
while(left<right)
{int mid=left+(right-left)/2;
if(a[mid]>a[n-1] || a[mid]<x) left=mid+1;
if(a[mid]>x && a[mid]<a[n-1] ) right=mid-1;
if(a[mid]==x) right = mid;
}
return a[left]==x?left:-1;
}
if(x>a[n-1])
{
while(left<right)
{int mid=left+(right-left)/2;
if(a[mid]>a[n-1] && a[mid]<x) {left=mid+1;}
if(a[mid]>x || a[mid]<a[n-1] ) {right=mid-1;}
if(a[mid]==x) {right = mid;}}
return a[left]==x?left:-1;
}
}int main()
{scanf("%d",&n);int x;scanf("%d",&x);for(int i=0;i<n;i++) scanf("%d",&num[i]); printf("%d",bis(num,0,n-1,n,x));
}
旋转序列找中位数:
找到最小值下标+数组长度/2(?)大概,懒得写了
双序列中位数
我用了类似归并排序的方法,代价就是时间复杂度O(n/2)
#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=100001;int n,m,num1[N],num2[N];
double s()
{int a=0,b=0,l=0,l0=(m+n)/2,num3[l0+1];int c=max(m,n);while(l<=l0+2 && a<=n-1 &&b<=m-1){if(num1[a]<=num2[b]) {num3[l]=num1[a];a++;l++;} else{num3[l]=num2[b];b++;l++;}}if(l<=l0+2){if(a==n) {for(int i=b;i<m&&l<=l0+1;i++){num3[l]=num2[i];l++;}};if(b==m) {for(int i=a;i<n&&l<=l0+1;i++){num3[l]=num1[i];l++;}};}if((m+n)&1) return num3[l0];else return (double(num3[l0])+num3[l0-1])/2;}int main()
{//printf("%lf",(double)9/2);scanf("%d",&n);scanf("%d",&m);for(int i=0;i<n;i++) scanf("%d",&num1[i]); for(int i=0;i<m;i++) scanf("%d",&num2[i]); printf("%.1f",s());
}
答案仍然是二分,但我没看懂
#include <cstdio>
#include <algorithm>
using namespace std;const int MAXN = 100000;
int n, m, a[MAXN], b[MAXN];int getMax(int a[], int i, int b[], int j) {if (i < 0) {return b[j];}if (j < 0) {return a[i];}return max(a[i], b[j]);
}int getMin(int a[], int i, int b[], int j) {if (i >= n) {return b[j];}if (j >= m) {return a[i];}return min(a[i], b[j]);
}double binarySearch(int n, int a[], int m, int b[]) {int leftPartCount = (n + m + 1) / 2;int l = 0, r = n;while (l < r) {int mid = (l + r + 1) / 2;int j = leftPartCount - mid;if (a[mid - 1] > b[j]) {r = mid - 1;} else {l = mid;}}if ((n + m) % 2) {return (double)getMax(a, l - 1, b, leftPartCount - l - 1);} else {return (getMax(a, l - 1, b, leftPartCount - l - 1) + getMin(a, l, b, leftPartCount - l)) / 2.0;}
}int main() {scanf("%d%d", &n, &m);for (int i = 0; i < n; i++) {scanf("%d", &a[i]);}for (int i = 0; i < m; i++) {scanf("%d", &b[i]);}if (n < m) {printf("%.1f", binarySearch(n, a, m, b));} else {printf("%.1f", binarySearch(m, b, n, a));}return 0;
}