算法设计与分析课程:第一次作业(我是个算法白痴。。。)

第一道题:
在这里插入图片描述这道题就不说了。。。。。

第二道题:
在这里插入图片描述这道题大概思路,其实说白了就是快排,因为每次进行快排的时候,所找到的那一个分割点的左边所有的数字都比该分割点的数字要小,右边都比该分割点的数字要大,因此当该分割点的下标与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]++;
                }
            }
        }
    }


}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值