蓝桥杯每日学习补充3

时间复杂度

我觉得关于时间复杂度没有什么好讲的,大一的时候程序基础大家应该都了解,这部分可以直接跳过啦。

枚举

定义:枚举算法我们也称之为穷举算法,这种算法就是在解决问题的时候去使用所有的方式去解决这个问题,会通过推理去考虑事件发生的每一种可能,最后推导出结果。

  • 优点:简单粗暴,它暴力的枚举所有可能,尽可能地尝试所有的方法。

  • 缺点:大部分题目使用枚举算法拿不到满分。

例题

1.标题统计

我的解法:

 import java.util.Scanner;
 // 1:无需package
 // 2: 类名必须Main, 不可修改
 ​
 public class Main {
     public static void main(String[] args) {
         Scanner scan = new Scanner(System.in);
         //在此输入您的代码...
         int count = 0;
         while(scan.hasNext()) {
             char[] arr = scan.nextLine().toCharArray();
             count+=arr.length;
             for(int i=0;i<arr.length;i++) {
                 if(arr[i]==' ') {
                     --count;
                 }
             }
         }
         System.out.print(count);
         scan.close();
     }
 }

其实这些题都相对比较简单,因为一天学习的开始都是要慢慢来,可以稍微过一遍就好,但是贵在每日坚持!

2.计数问题

 import java.util.Scanner;
 // 1:无需package
 // 2: 类名必须Main, 不可修改
 ​
 public class Main {
     public static void main(String[] args) {
         Scanner scan = new Scanner(System.in);
         //在此输入您的代码...
         int n = scan.nextInt();
         int x = scan.nextInt();
         String a = String.valueOf(x);
         int count = 0;
         char[][] arr = new char[n+1][];
         for(int i=1;i<=n;i++) {
             arr[i] = String.valueOf(i).toCharArray();
         }
         for(int i=1;i<=n;i++) {
             for(int j=0;j<arr[i].length;j++) {
                 if(arr[i][j]== a.charAt(0)) {
                     count++;
                 }
             }
         }
         System.out.print(count);
         scan.close();
     }
 }

这些题中总是有很多scan的读取数据的方法:这里需要同一总结。

3.next(),nextInt(),nextDouble(),nextLine

前三者可以认为是一类的。读到空格之前的部分。焦点不会移动到下一行,仍然处在这一行上。

next(),返回值是一个字符串

nextInt(),返回值是int

nextDouble(),返回值是double

当使用nextLine()方法时会读取改行从前到的所有的内容,包括换行符,然后把焦点移动到下一行的开头。也就是可以把空格,回车读出值为空。

所以说当前三种但凡跟nextLine()混着用的时候就要考虑多用一个nextLine()了来进行读取数据换行了。

4.质因数分解

关于质因数分解我想到了素数判断;

 import java.util.Scanner;
  
 public class HomeWork {
  
     public static void main(String[] args) {
             Scanner sc = new Scanner(System.in);
             System.out.println("请输入要判断的数字:");
             int n = sc.nextInt();
             int i = 2;
             for(;i <= Math.sqrt(n);i++){
                 if(n % i == 0){
                     System.out.println(n+"不是素数");
                     break;
                 }
             }
             if(i >Math.sqrt(n)){
                 System.out.println(n+"是素数");
             }
     }
 }

接下来是我对于这道题的解法:

 import java.util.Scanner;
 // 1:无需package
 // 2: 类名必须Main, 不可修改
 ​
 public class Main {
     public static void main(String[] args) {
         Scanner scan = new Scanner(System.in);
         //在此输入您的代码...
         int n = scan.nextInt();
         for(int i=2;i<Math.sqrt(n);i++) {
             if(n%i==0) {
                 System.out.print(n/i);
                 break;
             }
         }
         scan.close();
     }
 }

5.小蓝的漆房

解法:暴力枚举 因为题目中已经限制了颜色的个数,最多60个。那么本题的一个比较容易理解的方法是枚举每一种颜色(即将所有房子变成60种颜色中的一种),计算60种情况下哪个情况下所需要的天数最少。

我的解法:

 import java.util.LinkedList;
 import java.util.Queue;
 import java.util.Scanner;
 // 1:无需package
 // 2: 类名必须Main, 不可修改
 ​
 public class Main {
     public static void main(String[] args) {
         Scanner scan = new Scanner(System.in);
         //在此输入您的代码...
         int t = scan.nextInt();
         for(int i=0;i<t;i++) {
             int n = scan.nextInt();
             int k = scan.nextInt();
             int []arr_ = new int[n];
 ​
             for(int j=0;j<n;j++) {
                 arr_[j] = scan.nextInt();
             }
             
             int min = Integer.MAX_VALUE;
             for(int m=1;m<=60;m++) {
                 int []arr = arr_.clone();
                 int count = 0;
                 int index=0;
                 while(index<n)
                 {   
                     if(arr[index]==m) {
                         ++index;
                         continue;
                     }
                     else {
                         count++;
                         for(int p=0;p<k&&index<n;p++) {
                             arr[index] = m;
                             ++index;
                         }
                         }
                 }
                 if(min>count) min = count;
                 }
             System.out.println(min);
         }
         scan.close();
     }
 }

这道题看似暴力枚举,实际上还有不少的坑。比如每次要及时更新数组,

int []arr = arr.clone(); 这个才是深拷贝,若是int []arr = arr_是无济于事的。

在 Java 中实现数组复制分别有以下 4 种方法:

  1. Arrays 类的 copyOf() 方法

  2. Arrays 类的 copyOfRange() 方法

  3. System 类的 arraycopy() 方法

  4. Object 类的 clone() 方法

在以上四个方法中只有clone是深拷贝。

例题串处理

 import java.util.Scanner;
 // 1:无需package
 // 2: 类名必须Main, 不可修改
 ​
 public class Main {
     public static void main(String[] args) {
         Scanner scan = new Scanner(System.in);
         //在此输入您的代码...
         char []arr = scan.nextLine().toCharArray();
         char []expert = new char[2*arr.length];
         int index=0;
         for(int i=0;i<arr.length;) {
             //多个空格情况
             if(arr[i]==' ') {
                 i++;
                 if(index!=0) {
                     expert[index++] = ' ';
                 }
                 while(arr[i]==' ') {
                     i++;
                 }
                 continue;
             }
             //小写字母需要变的情况
             //You中的Y字符串中的第一个字符需要大写
             //And中的A遇到前面一个字符是空格需要大写
             if((i>0&&arr[i-1]==' '&&arr[i]>='a'&&arr[i]<='z')||index==0&&arr[i]>='a'&&arr[i]<='z') {
                 expert[index++]= (char) (arr[i++]^32);
                 continue;
             }
             //小写字母不用变的情况
             //You中的ou只看前一个字符是否是字母
             //2005_program中的p看前一个字符是否为'_'
             //需要在if里面再进行判断字母后所跟的是不是数字,若为数字再赋值expert一个'_'
             if (i > 0 && i < arr.length && (arr[i-1] >= 'a' && arr[i-1] <= 'z' && arr[i] >= 'a' && arr[i] <= 'z') || 
                     (index > 0 && expert[index-1] == '_' && arr[i] >= 'a' && arr[i] <= 'z')) {
                 if(i<arr.length-1&&arr[i+1]>='0'&&arr[i+1]<='9') {
                     expert[index++]=arr[i++];
                     expert[index++]='_';
                     continue;
                 }
                 expert[index++]=arr[i++];
                 continue;
             }
             //数字的赋值情况
             //一般遇到数字就直接赋值需要在if里面再进行判断数字后所跟的是不是字母,若为数字再赋值expert一个'_'
             if(arr[i]>='0'&&arr[i]<='9') {
                 if(i<arr.length-1&&arr[i+1]>='a'&&arr[i+1]<='z') {
                     expert[index++]=arr[i++];
                     expert[index++]='_';
                     continue;
                 }
                 expert[index++]=arr[i++];
                 continue;
             }
             i++;
         }
         
         for(int i=0;i<index;i++) {
                 System.out.print(expert[i]);
         }
 ​
         scan.close();
     }
 }

通过率百分之40。

DNA修正序列

 import java.util.HashMap;
 import java.util.Map;
 import java.util.Scanner;
 public class Main {
 public static void main(String[] args) {
 // TODO Auto-generated method stub
 // 读入数据
     Scanner sc = new Scanner(System.in);
     int n = sc.nextInt();
     sc.nextLine();
     char[] sq1 = sc.next().toCharArray();
     sc.nextLine();
     char[] sq2 = sc.next().toCharArray();
     Map<Character, Integer> map = new HashMap<>();
     map.put('A', 0);
     map.put('C', 1);
     map.put('G', 2);
     map.put('T', 3);
     int res = 0;
     for(int i = 0; i < n; ++i) {
         if(map.get(sq1[i]) + map.get(sq2[i]) != 3) {
             for(int j = i + 1; j < n; ++j) {
                 if(map.get(sq1[i]) + map.get(sq2[j]) == 3 &&
                         map.get(sq1[j]) + map.get(sq2[i]) == 3) {
                     char c = sq2[i];
                     sq2[i] = sq2[j];
                     sq2[j] = c;
                     break;
                     }
                 }
             ++res;
             }
         }
     System.out.println(res);
     // 关闭资源
     sc.close();
     }
 }

注意在代码中并没有刻意指出需要将第二个序列的字符替换为A、C、G、T中的任意一个。因为循环后如果没有下面这种情况:

 if(map.get(sq1[i]) + map.get(sq2[j]) == 3 &&
                         map.get(sq1[j]) + map.get(sq2[i]) == 3) {
                     char c = sq2[i];
                     sq2[i] = sq2[j];
                     sq2[j] = c;
                     break;
                     }

也会进行res++;这时就包含了将第二个序列的字符替换为A、C、G、T中的任意一个的情况。

这种使用Hashtable来进行操作的方法很值得借鉴。

递归

数的计算

不太理解题目的意思,于是我搜了一下另外一种题目描述: 给出自然数n,要求按如下方式构造数列: 1.只有一个数字n的数列是一个合法的数列。 2.在一个合法的数列的末尾加入一个自然数,但是这个自然数不能超过该数列最后一项的一 半,可以得到一个新的合法数列。 也就是新加的数不能超过前一个数的一半,最后求序列有多少个数

 import java.util.HashMap;
 import java.util.Map;
 import java.util.Scanner;
 public class Main {
     public static int count = 0;
 public static void main(String[] args) {
 // TODO Auto-generated method stub
 // 读入数据
     Scanner scan = new Scanner(System.in);
 ​
     int n = scan.nextInt();
     count_num(n);
     System.out.println(count+1);
     scan.close();
     }   
     static void count_num(int n) {
         if(n/2==0) {
             return;
         }
         for(int i=n/2;i>=1;i--) {
             count++;
             count_num(i);
         }
 ​
         
     }
 }

计算函数值

 import java.util.HashMap;
 import java.util.Map;
 import java.util.Scanner;
 public class Main {
     public static void main(String[] args) {
     Scanner scan = new Scanner(System.in);
     int x = scan.nextInt();
     System.out.println(garden(x));
     scan.close();
     }
     static int garden(int x) {
         if(x==0) {
             return 1;
         }
         if(x%2==0) {
             return garden(x/2);
         }else {
             return garden(x-1)+1;
         }
     }
 }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值