挑战程序设计竞赛讲解 ——抽签问题

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

算法设计的时候,当输入数据过大,会导致程序崩溃,所以复杂度尤为重要,留下痕迹再走哦!


一、问题是什么?

 

 

二、思路与实现

1.暴力搜索 ,四重循环解决

代码如下:

import java.util.Scanner;

public class 抽签 {
    
    static int N;
    static int M;
    static int[] cq = new int[50];
    static Boolean flag = false;

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        //输入数据
        N = sc.nextInt();
        M = sc.nextInt();
        for(int i = 0; i < N; i++){
            cq[i] = sc.nextInt();
        }

        // 哈哈哈,进行四重循环遍历
            //复杂度为O(n**4)

        for(int a = 0; a < N; a++){
            for(int b = 0; b < N; b++){
                for(int c = 0; c < N; c++){
                    for(int d = 0; d < N; d++){
                        if(cq[a] + cq[b] + cq[c] + cq[d] == M){
                            flag = true;
                        }
                    }
                }
            }
        }


        if(flag){
            System.out.println("Yes");
        }else{
            System.out.println("No");
        }

    }
}

2.次升级版

可以让 m - a1 - a2 - a3 对于原来的数组进行二分查找  将一个 n 将为了 log n

代码如下:

import java.util.Arrays;
import java.util.Scanner;

public class 抽签次级版 {

    static int N;
    static int M;
    static int[] cq = new int[50];
    static Boolean flag = false;



    public static int binary_search(int x) {  //这个方法是个普通的二分查找 复杂度你懂的了 logn

        int l = 0, r = N-1;

        while(l <= r){
            int mid = (l + r) / 2;
            if(cq[mid] == x){
                return 1;
            }else if(cq[mid] > x){
                r = mid - 1;
            }else{
                l = mid + 1;
            }
        }
        return 0;
    }

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        //输入数据
        N = sc.nextInt();
        M = sc.nextInt();
        for(int i = 0; i < N; i++){
            cq[i] = sc.nextInt();
        }

        Arrays.sort(cq);

        // 哈哈哈,进行三重循环遍历加上一个查找
        //复杂度为O(n ** 3 *log n)

        for(int a = 0; a < N; a++){
            for(int b = 0; b < N; b++){
                for(int c = 0; c < N; c++){
                    if(binary_search( M - cq[a] - cq[b] - cq[c])  == 1){
                        flag = true;
                    }
                }
            }
        }


        if(flag){
            System.out.println("Yes");
        }else{
            System.out.println("No");
        }

    }
}

3.升级版

可以让a1 + a2 = m - a3 - a4  这个就把两层循环压缩了   要算出 a1 + a2 的值了

代码如下:

import java.util.Arrays;
import java.util.Scanner;

public class 抽签升级版 {

    static int N;
    static int M;
    static int[] cq = new int[50];
    static int[] cq1 = new int[2500];
    static Boolean flag = false;



    public static int binary_search(int x) {  //这个方法是个普通的二分查找 复杂度你懂的了 logn

        int l = 0, r = N * N - 1;

        while(l <= r){
            int mid = (l + r) / 2;
            if(cq[mid] == x){
                return 1;
            }else if(cq[mid] > x){
                r = mid - 1;
            }else{
                l = mid + 1;
            }
        }
        return 0;
    }

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        //输入数据
        N = sc.nextInt();
        M = sc.nextInt();
        for(int i = 0; i < N; i++){
            cq[i] = sc.nextInt();
        }

        //算出 这个数组两两相加的结果
        for(int i = 0; i < N; i++){
            for(int j = 0; j < N ; j++){
                cq1[i * N + j] = cq[i] + cq[j];
            }
        }

        Arrays.sort(cq1);

        // 哈哈哈,进行三重循环遍历加上一个查找
        //复杂度为O(n ** 3 *log n)

        for(int a = 0; a < N; a++){
            for(int b = 0; b < N; b++){
               if( binary_search(M - cq[a] - cq[b]) == 1){
                   flag = true;
               }
            }
        }


        if(flag){
            System.out.println("Yes");
        }else{
            System.out.println("No");
        }

    }
}


总结

优化算法还是很重要的,哈哈哈,不妨点个赞关注一下再走。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

聪明快乐的小智

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值