小M给你一个长度为n的数组,我们定义median数为该数组从小到大排序后,下标为(n-1)/2的数字。下标从0开始,(n-1)/2表示整数除法,即向下取整。现在我们已经得到了一个初始的数组,我们希望这个数组的median数是一个给定数字x。所以我们需要加入一些数到数组中从而完成我们的目标。数组中的元素可以重复,请问,最少需要加入多少个数字才能达成这个目标。
小M给你一个长度为n的数组,我们定义median数为该数组从小到大排序后,下标为(n-1)/2的数字。下标从0开始,(n-1)/2表示整数除法,即向下取整。现在我们已经得到了一个初始的数组,我们希望这个数组的median数是一个给定数字x。所以我们需要加入一些数到数组中从而完成我们的目标。数组中的元素可以重复,请问,最少需要加入多少个数字才能达成这个目标。
第一行输入两个整数n x (1 <= n <= 500, 1 <= x <= 10^5)。
接下来一行有n个正整数表示初始的数组,用空格分开,范围是[1, 10^5]。
输出需要加入最少的元素个数才能够使得新数组的median数成为x。
3 2 2 3 4
1
样例一中,加入1,得到1 2 3 4,那么median数的下标为(4 - 1)/2 = 1, median数为2。加一个数字就可以了。
3 4 1 2 3
4
样例二中,加入4 5 6 7,得到1 2 3 4 5 6 7,median数为4。最少加4个数字。
import java.util.*; public class Main{ public static void main(String[]args){ Scanner sc=new Scanner(System.in); //至少添加的次数,即结果 int res=0; int nums=sc.nextInt(); int target=sc.nextInt(); //小于中位数的个数 int min=0; //大于中位数的个数 int max=0; //等于中位数的个数 int same=0; //中位数是否存在 boolean isExist=false; for(int i=0;i<nums;i++){ int temp=sc.nextInt(); if(temp>target){ max++; } else if(temp<target){ min++; } else if(temp==target){ //中位数已存在,保存多出来的个数 if(isExist){ same++; }else{ isExist=true;} } } //如果不存在中位数,添加中位数,次数加一 if(isExist==false) res++; //如果max大于min的时候,记录差值为dif //如果dif大于same时,中位数的左边要添加dif-same-1个数组 //举例:中位数为3 1 2 3 3 3 4 4 4 4 4 4 4 //因为中位数永远位于左边,所以可以少添加一个 //如果dif小于same时,添加0 //举例: 中位数为3 1 2 2 3 3 3 3 4 4 4 4 if(max>min){ int dif=max-min; dif=dif>same?dif-same-1:0; res+=(dif); } //如果min大于max情况的时候 ,记录差值为dif //如果dif大于same时 中位数的右边要添加dif-same个数字:举例 中位数为3 1 2 2 2 2 3 3 4 4 //如果dif小于等于same时 添加0:举例 中位数为3 1 2 2 2 3 3 3 3 4 else if(min>max){ int dif=min-max; dif=dif>same?dif-same:0; res+=(dif); } System.out.print(res); } }
"""" n最大为500,暴力尝试 """ def median(a, x): ans = 0 if a[(len(a) - 1) // 2] == x: ans = 0 while a[(len(a) - 1) // 2] > x: a.insert(0, a[0]) ans += 1 while a[(len(a) - 1) // 2] < x: a.append(a[-1]) ans += 1 return ans if __name__ == "__main__": n, x = map(int, input().strip().split()) a = list(map(int, input().strip().split())) if x in a: a.sort() ans = median(a, x) else: a.append(x) a.sort() ans = median(a, x) + 1 print(ans)
#include<iostream> using namespace std; int main(){ int n,x; cin>>n>>x; int a[n]; int m = (n-1)/2, left=0, right=0, count=0; for(int i=0;i<n;i++){ cin>>a[i]; if(a[i]==x) count++; else if(a[i]<x) left++; else right++; } if(left<=m){//排序后有x在m的左边或者x位置上 if(m<n-right)//有x恰好在m位置上 cout<<0<<endl; else//需要在最右边的x上往左边添数 //最右边x的右边的数字有right个,它的左边有left+count-1个 //我们需要保证补数字后,它左边的数字比右边刚好少一个 //即add=right-(left+count-1)-1==right-left-count cout<<right-left-count<<endl; }else{//排序后,x在m的右边,这个时候往最左边的x的右边补数后,最左边的x左边的数和右边的数应该相等 //左边的数是left个,右边的数是right+count-1个 cout<<left-(right+count-1)<<endl; } return 0; }我给大佬的代码自己过了一遍,和大家分享。
if __name__=='__main__': n,x = input().split() n = int(n) x = int(x) arr = [int(x) for x in input().split()] # count left = right = same = 0 for i in arr: if i > x: right += 1 elif i < x: left += 1 else: same += 1 # cal if right > left: need = max(right - left - same,0) elif left > right: need = max(left - right - same + 1,0) else: if same == 0: need = 1 else: need = 0 print(need)
#include<bits/stdc++.h> using namespace std; int main(){ ios::sync_with_stdio(false); cin.tie(0); int n,x; cin>>n>>x; int a[n]; int m=(n-1)/2,l=0,r=0,e=0; for(int i=0;i<n;i++){ cin>>a[i]; if(a[i]==x) e++;//记录数组中等于给定值的个数 else if(a[i]<x) l++;//数组中给定值左边的个数 else r++;//数组中给定值右边的个数 } if(l<=m){ //给定值左边的个数 小于 给定值的位置;即左边的个数不够 if(r<n-m) //给定值右边的个数不够 cout<<0<<endl; //数组中,给定值左边的不够,右边的也不够,所以中间的一些值都是给定值;故不需要添加数字 else //右边的个数多,所以左边添加个数 cout<< r-l-e<<endl; // 因为需要左边添加个数,所以将给定值当做左边的。这样可以尽可能少的添加 }else{ //左边的个数多 cout<<l-r-e+1<<endl; //需要添加右边的,所以将等于给定值的数当做右边的;同时由于m的位置是向下取整,因此右边需要多加1 } return 0; }
#include <bits/stdc++.h> using namespace std; int main() { int n,x,res=0; cin>>n>>x; vector<int> nums(n); for(int i=0;i<n;i++) cin>>nums[i]; int flag = 1; for(int i=0;i<n;i++) if(nums[i] == x) flag = 0; if(flag) { nums.push_back(x); n++; } sort(nums.begin(),nums.end()); int left = -1; int right = -1; for(int i=0;i<n;i++) { if(x == nums[i]) { if(left == -1) { left = i; right = i; } else right = i; } } int target = (n-1)/2; if(target < left) while(left > (n-1 + res)/2) res++; else if(target > right) while(right + res < (n-1 + res)/2) res++; cout<<res+flag<<endl; return 0; }
#include <bits/stdc++.h> using namespace std; int main(){ int n,x; cin>>n>>x; int a[n]; int m = (n-1)/2, l=0, r=0, e=0; for(int i=0;i<n;i++){ cin>>a[i]; if(a[i]==x) e++; else if(a[i]<x) l++; else r++; } if(l<=m){ if(r<n-m) cout<<0<<endl; else cout<<r-l-e<<endl; }else{ cout<<l+1-r-e<<endl; } return 0; }
#include<stdio.h> #define maxn 1000 int a[maxn]; // 快速排序函数 void quickSort(int l, int r) { if (l >= r) { // 递归结束条件:区间只有一个元素或区间为空 return; } int i = l, j = r, pivot = a[l]; // 定义左右指针和枢轴元素 while (i < j) { // 左右指针相遇时退出循环 while (i < j && a[j] >= pivot) { // 右指针向左移动,找到第一个小于枢轴元素的元素 j--; } a[i] = a[j]; // 将该元素赋值给左指针所在位置 while (i < j && a[i] <= pivot) { // 左指针向右移动,找到第一个大于枢轴元素的元素 i++; } a[j] = a[i]; // 将该元素赋值给右指针所在位置 } a[i] = pivot; // 将枢轴元素放到最终正确的位置上 quickSort(l, i - 1); // 对左半部分区间递归进行快排 quickSort(i + 1, r); // 对右半部分区间递归进行快排 } int main() { int n, x, i; scanf("%d%d", &n, &x); // 输入数组长度和要插入的元素 for (i = 0; i < n; i++) { scanf("%d", &a[i]); // 输入原始数组 } quickSort(0, n - 1); // 对原始数组进行排序 int cnt = 0; // 记录插入次数 while (a[(n - 1) / 2] != x) { // 当中位数不等于要插入的元素时循环 if (a[(n - 1) / 2] > x) { // 如果中位数大于要插入的元素 for (int k = n; k > (n + 1) / 2; k--) { // 将中位数及其右边的元素全部向右移动一位 a[k] = a[k - 1]; } a[(n + 1) / 2] = x; // 将要插入的元素放到新的中间位置 } else { // 如果中位数小于要插入的元素 for (int k = n; k >= (n + 1) / 2; k--) { // 将中位数及其右边的元素全部向右移动一位 a[k] = a[k - 1]; } a[(n - 1) / 2] = x; // 将要插入的元素放到新的中间位置 } cnt++; // 插入次数加1 n++; // 数组长度加1 quickSort(0, n - 1); // 对新的数组进行排序 } printf("%d\n", cnt); return 0; }
import sys n, x = map(int, sys.stdin.readline().strip().split()) a = list(map(int, sys.stdin.readline().strip().split())) l_x, r_x, n_x = 0, 0, 0 for ai in a: if ai < x: l_x += 1 elif ai > x: r_x += 1 else: n_x += 1 if l_x >= r_x: res = max(0, l_x - r_x - n_x + 1) else: res = max(0, r_x - l_x - n_x) print(res)
//让我想到了快排一次的partition,按照 x partition一下吗 //存在的问题:数组里允许有重复数字吗?可以哦, import java.util.*; public class Main{ public static void main(String args[]){ Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int x = scanner.nextInt(); int nums[] = new int[n+1]; int index = -1; int count_x = 0; for(int i=0;i<n;++i){ nums[i]=scanner.nextInt(); if(nums[i]==x) { count_x++; index=i; } } scanner.close(); if(count_x==0){ //没有x加一个进来 nums[n]=nums[0]; nums[0]=x; index=0; count_x=1; System.out.println(howManyToInsert(nums,n+1,x,index,count_x)+1); } else { if(index!=0){ //做一个处理 int temp = nums[0]; nums[0]=nums[index]; nums[index]=temp; } System.out.println(howManyToInsert(nums,n,x,index,count_x)); } } private static int howManyToInsert(int nums[],int len,int x,int index,int count_x){ //首先按照x进行一次partition //记录x的个数 //如果没有x怎么办? int howMany = 0; /*if(count_x==0){ //没有x;加一个进来 O(n)时间复杂度O(n)空间复杂度 int temp[] = new int[len+1]; temp[0]=x; for(int i=1;i<=len;++i){ temp[i]=nums[i-1]; } nums=temp; temp=null; howMany+=1; count_x+=1; index=0; }*///这种想法实在太慢了 int low = 0; int high = len-1; while(low<high){ while(low<high&&nums[high]>=x){ high--; } nums[low]=nums[high]; while(low<high&&nums[low]<x){ low++; } nums[high]=nums[low]; } nums[low]=x; //low就是现在x的第一个位置 int median = (len-1)/2; if(low<median){ while(low+count_x-1<(len+howMany-1)/2){ //这种情况下怎么添加更好呢? //只要有添加,右边的每两次增长1 //a.添加大于x肯定不行 //b.添加小于x:low肯定要增加1每次 //c.添加等于x:coung_x肯定每次增加1 //所以b和c是一样的 howMany+=1; low++; } return howMany; } else if(low>median){ while(low>(len+howMany-1)/2){ //只要有添加,右边没两次增加1 //a.添加小于x的,low每次增1 //b.添加大于x的,low每次不变 //c.添加等于x的,low不变 //所以我肯定要使得low减少或者不变的 howMany++; } return howMany; } return howMany; } }
#include<vector> #include<algorithm> #include<iostream> using namespace std; int InsertNum(vector <int> &v,int L,int x){ int right=0,left=0,eql=0; for(int i=0;i<L;i++){ if(v[i]==x)eql++; if(v[i]<x)left++; if(v[i]>x)right++; } if(left<right+eql){ if(left+eql>=right)return 0; else {//在左边添加 总数应该为偶数; return 2*right-L; } }else{//在右边添加应该总数为奇数; return 2*left-L+1; } } int main(){ int n; int x; vector<int>v; cin>>n; cin>>x; int temp=n; while(temp--){ int a; cin>>a; v.push_back(a); } cout<<InsertNum(v,n,x); return 0; }
int median(int n, unsigned int x, std::vector<unsigned int> arr) { int less = 0, high = 0, equal = 0; //分别表示array中数与x比较的个数——小,大,等 for(int i = 0; i < n; i++) { if(arr[i] == x) { ++equal; } else if(arr[i] < x) { ++less; } else { ++high; } } int add = 0; //需要增加的数的个数 // 下面通过左边的数和右边的数进行抵消来判断增加的数 if(less == high) { if(equal == 0) { add = 1; } else { add = 0; } } else if(less < high) { if((high - less) < equal) { add = 0; } else { add = high - less - equal; } } else { if((less - high) < equal) { add = 0; } else { add = less - high - equal + 1; } } return add; }
#include<bits/stdc++.h> #include <algorithm> using namespace std; int main(){ int a[1000]; int n,m; while(~scanf("%d %d",&n,&m)){ int f=1000,l=0,flag=0,ans=0; for(int i=0;i<n;i++){ scanf("%d",&a[i]); if(a[i]==m)flag++; } //判断是否存在,不存在就插入一个 if(flag==0){ a[n]=m; n++; ans++; } sort(a, a + n); for(int i=0;i<n;i++){ if(a[i]==m){ if(f>i)f=i; if(l<i)l=i; } } int mid=(n-1)/2; if(a[mid]==m){ printf("%d\n",0+ans); } else if(a[mid]>m){ printf("%d\n",n-1-2*l-1+ans); } else{ printf("%d\n",2*f+1-n+ans); } } return 0; }
import java.util.*; public class Main { public static void main(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int x = sc.nextInt(); int[] array=new int[n]; int left=0; int right=0; int xcount=0; int result=0; for(int i=0;i<n;i++) { int num = sc.nextInt(); if(num==x) xcount++; else if(num<x) left++; else if(num>x) right++; } if(xcount==0) { xcount++; result++; } if(left+xcount<right) { result+=(right-(left+xcount)); System.out.println(result); return; } else if(left>=right+xcount) { result+=(left-(right+xcount)+1); System.out.println(result); return; } else { System.out.println(result); return; } } }
#include<iostream> #include<vector> using namespace std; int main(){ int n, median; cin>>n>>median; int index = (n-1)/2; int less = 0, high = 0, equal = 0; vector<unsigned int> nums; unsigned int temp = 0; for(int i=0; i<n; i++){ cin>>temp; nums.push_back(temp); if(temp==median){ equal++; }else{ if(temp<median){ less++; }else{ high++; } } } if(less==high){ //如果小的数和大的数的数量相同,此时要判断median是否在输入序列中 if(equal>0) cout<<0; else cout<<1; }else{ if(less<high){ //如果小的数小于大的数,首先相互抵消,还剩high-less个数 if(high-less<equal){ //注意隐含了equal>0这个条件(因为high-less一定是大于0的) cout<<0; }else{ cout<<high-less-equal; } }else{ if(less-high<equal){ cout<<0; }else{ cout<<less-high-equal+1; } } } return 0; }
import java.io.*; import java.util.Arrays; public class Main{ public static void main(String[] args) throws IOException{ BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); String[] line1=br.readLine().split(" "); int n=Integer.parseInt(line1[0]); int x=Integer.parseInt(line1[1]); String[] line2=br.readLine().split(" "); int[] nums=new int[n]; int l=0,e=0,h=0; for(int i=0;i<n;i++){ nums[i]=Integer.parseInt(line2[i]); if(nums[i]==x){ e++; }else if(nums[i]<x){ l++; }else{ h++; } } if(l<=(n-1)/2 && (n-1)/2<=l+e-1){ System.out.println(0); }else if(l>h){ System.out.println(l-(h+e-1)); }else if(l<h){ System.out.println(h-(l+e-1)-1); }else{//用于解决l==h的部分 System.out.println(1); } } }三向切分快速排序的变式
import java.util.Scanner; import java.util.Arrays; //未考虑到中位数存在很多时,二分法查找不准 //解决方案,找到第一个和最后一个的位置,再分别计算需要添加的数量后取最少的。 //此方案是在输入数据时就事先找到位置。可以省去排序和查找的时间。 //计算结果时可以再优化,因为之前是根据二分查找的返回值计算的。 public class Main{ public static void main(String[] args){ //scan parameter Scanner in = new Scanner(System.in); int num = in.nextInt(); int x = in.nextInt(); int[] array = new int[num]; int pos = -1, l = -1, h = -1;//l和h分别记录低位和高位位置 for(int i = 0; i < num; i++){ array[i] = in.nextInt(); //此时就开始查找x的位置 if(array[i] < x){ pos = pos<0? pos-1: pos+1; l++; h++; } if(array[i] == x){ if(pos < 0){ l = h = pos = -pos-1; }else{ h++; } } } //function realize if(pos < 0){ int temp = num+2*pos+2; System.out.println(temp > 0 ? temp : 1-temp); }else{ int temp1 = num-2*l-1 > 0 ? num-2*l-1-1 : -(num-2*l-1); int temp2 = num-2*h-1 > 0 ? num-2*h-1-1 : -(num-2*h-1); System.out.println(temp1 < temp2 ? temp1 : temp2); } } }