第一道题:
这道题就不说了。。。。。
第二道题:
这道题大概思路,其实说白了就是快排,因为每次进行快排的时候,所找到的那一个分割点的左边所有的数字都比该分割点的数字要小,右边都比该分割点的数字要大,因此当该分割点的下标与K相等的时候,就找到了
package One;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
public class Second{
public static void main(String[] args) {
Comparable[]data = init(100);
int k=29;
System.out.println(Find_K_Number(data,0,data.length-1, k-1));
Arrays.sort(data);
System.out.println("以下两行数据为验证答案");
for (Comparable a:data)
{
System.out.print(a+" ");
}
System.out.println("");
System.out.println(data[28]);
}
public static void swap(Comparable[]data,int i,int j)
{
Comparable temp = data[i];
data[i] = data[j];
data[j] = temp;
}
public static int partition(Comparable[]data,int lo,int hi)
{
int i = lo;
int j = hi+1;
Comparable privot = data[lo];
while (true)
{
while (data[++i].compareTo(privot)<0)
{
if(i==hi)break;
}
while (data[--j].compareTo(privot)>0)
{
if(j==lo)break;
}
if(i>=j)break;
swap(data,i,j);
}
swap(data,lo,j);
return j;
}
public static Comparable Find_K_Number(Comparable[]data,int lo,int hi,int k)
{
int flag = partition(data,lo,hi);
if(flag==k)
{
return data[flag];
}
else if(flag<k)
{
return Find_K_Number(data,flag+1,hi,k);
}
else return Find_K_Number(data,lo,flag-1,k);
//return -1;
}
public static Comparable[] init(int N)
{
Random random = new Random();
HashSet<Comparable> hashSet = new HashSet<>();
int count=0;
//利用HashSet的原因主要是为了防止重复
while (true)
{
Integer n = random.nextInt(N);
if(!hashSet.contains(n))
{
hashSet.add(n);
count++;
}
if(count==50)break;
}
//如果上面没有去重,接下来的代码属于去重代码:利用hashmap去重
// HashMap<Comparable,Integer> hashMap = new HashMap<>();
// for(Comparable a:data)
// {
// if(!hashMap.containsKey(a))
// {
// hashMap.put(a,1);
// }
// }
return hashSet.toArray(new Comparable[50]);
}
}
输出内容有三行,第一行是通过分治法算出来的,后两行是验证。
第三题:
注意这里的N是任意的!!!!做了好半天也没做出来,最后发现了一个很神奇的思路:第一天的安排就是:第一个队伍和最后一个队伍比,第二个队伍和倒数第二个队伍比,以此类推。。当比完之后,此时第一天已经结束了。然后将最后一个队伍,插入到第一个队伍之前,第二天开始,然后重复上述步骤,最终就可以得到结果,如果是奇数的话,可以在队尾加个0,当某只队伍和0比时,可以理解为他们队伍今天不打比赛
package One;
import java.util.LinkedList;
public class Third {
private int num;
private LinkedList<Integer> list = new LinkedList<>();
public Third(int n)
{
num=n;
init();
}
private void init()
{
if(num%2==0)
{
for(int i=0;i<num;i++)
{
list.add(i+1);
}
}
else
{
for(int i=0;i<num;i++)
{
list.add(i+1);
}
list.add(0);
}
}
private void print()
{
for(int i=1;i<=num-1;i++)
{
System.out.println("第"+i+"天");
for(int j=0;j<num/2;j++)
{
System.out.println(list.get(j)+"==="+ list.get(list.size()-1-j));
}
int temp = list.pollLast();
list.add(1,temp);
}
}
public static void main(String[] args)
{
Third d = new Third(9);
d.print();
}
}
第四题:
从网上找到的求字典序的算法:
package One;
import java.util.Scanner;
// 字典序值求法:
// 给出一个排列p(0)p(1)p(2)···p(n-1);
// 字典值sum=b[0] * (n-1)!+b[1] * (n-2)!+b[2] * (n-3)!+…+b[n-2]
// b[i]是p(i)对应的‘序数’,它代表着p(i)的右边比p(i)小的个数。
// 下一个序列的求法:
// 找到从右侧最大降序列p(i+1)p(i+2)…p(n-1),记录这序列的前一位下标i,再求p(i)最右侧值大于p(i)的p(k);
// 交换p(i)和p(k)。操作后的序列也就是下一个序列
public class Last
{
static Scanner scanner = new Scanner(System.in);
static int temp=1;
static int sum=0;
public static void main(String[] args) {
int n;
int []data = new int[100];
int []aux = new int[100];
n=scanner.nextInt();
for(int i=0;i<n;i++)
{
data[i]=scanner.nextInt();
}
getAux(data,aux,n);
getNum(n-2,aux,n);
System.out.println(sum+1);
getNext(n,data);
}
private static void getNext(int n, int[] data) {
int m=0;
int k=0;
for(int i=n-1;i>=1;i--)
{
if(data[i-1]<=data[i])
{
m=i-1;
break;
}
}
for(int i=m+1;i<n;i++)
{
if(data[i]>data[m])
{
k=i;
}
}
temp=data[m];
data[m]=data[k];
data[k]=temp;
for(int i=0;i<n;i++)
{
System.out.print(data[i]+" ");
}
}
private static void getNum(int a, int[] aux,int n) {
if(temp==n)return;
for (int i=1;i<=temp;i++)
{
aux[a]*=i;
}
sum+=aux[a];
temp++;
a--;
getNum(a,aux,n);
}
private static void getAux(int[] data, int[] aux, int n)
{
for (int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(data[i]>data[j])
{
aux[i]++;
}
}
}
}
}