牛客2018.7模拟考编程题

前言:

  今天的编程题不让用本地IDE,所以很难受QAQ,期间靠意念导了几个包,疯狂测试到底是不是正确的路劲,我们来复习一下常用的类所在的包吧!

  在模拟考之后打开eclipse看了看包名,总结一下常用的集合(工具)类都是“java.util.?”,比如java.util.LinkedList,与线程有关的都是“java.util.concurrent.?”,刷题的话,一般用工具类就够了。

 

正文:

  水题1号:

  乍一看题目很厉害的样子,仔细读了大概两三分钟发现是个水题,遍历一遍输入的数字,判断每个数字能被2除几次就行了,当我理解题意的那一刻,有种被欺骗的感觉!

 1 import java.util.Scanner;
 2 public class Main {
 3     public static void main(String[] args) {
 4         Scanner in = new Scanner(System.in);
 5         while (in.hasNextInt()) {//注意while处理多个case
 6             int num = in.nextInt();
 7             int result = 0;
 8             for(int i = 0; i<num; i++){
 9                 result += helper(in.nextInt());//每次判断数字能被2除几次
10             }
11             System.out.println(result);
12         }
13     }
14     static int helper(int n){
15         if(n == 0)
16             return 0;
17         int res = 0;
18         while(n % 2== 0){
19             n/=2;
20             res++;
21         }
22         return res;
23     }
24 }

  把整个代码都贴出来了,helper中判断n是否是0是为了防止测试用例偷偷地有0的情况(虽然说了数字范围比1大)。

  水题2号:

  题意很简单,求x的y次和y的x次哪个大,做题的时候没想到求用log把x^y和y^x去除求幂的操作,直接求logx/logy和logy/logx即可。

  做题的时候第一感觉就是幂大的那个数肯定大,除去2^4和4^2相等的这种情况,刷题的时候也没多想,把x,y小的几种情况都列出来,稍微大一点的就直接按幂大的数更大来做,ac了。

 1 import java.util.Scanner;
 2 public class Main {
 3     public static void main(String[] args) {
 4         Scanner in = new Scanner(System.in);
 5         while (in.hasNextInt()) {//注意while处理多个case
 6             int a = in.nextInt();
 7             int b = in.nextInt();
 8             if(a == b){
 9                 System.out.println("=");
10             }else if(a == 1){
11                 System.out.println("<");
12             }else if(b == 1){
13                 System.out.println(">");
14             }else if(a == 3 && b == 2){
15                 System.out.println(">");
16             }else if(a == 2 && b == 3){
17                 System.out.println("<");
18             }else if(a == 2 && b == 4){
19                 System.out.println("=");
20             }else if(a == 4 && b == 2){
21                 System.out.println("=");
22             }else{
23                 if(a > b){
24                     System.out.println("<");
25                 }else{
26                     System.out.println(">");
27                 }
28             }
29         }
30     }
31 }

  有点像数学题的意思。

  看起来像是水题的题:

  第三题的图被我拍糊了qaq,等牛客把题目放出来再补图吧,先凑活看看

  题目大意就是给你一串只有'('、')'这两个符号的字符串,求任意两个能构成合法括号字符串的数量。比如说s和j都是合法的,那么有sj、js、s、j四种(后两种其实可以理解成ss和jj)。

  我的想法就是对每个字符串判断,用数字代表字符串的合法性,当遇到(就加一,遇到)就减一,如果当前数字是0且遇到)则肯定不能放在第一个位置(代码中将其-10000000)。

  然后将数组排序,遍历一遍数组,二分找有没有符合条件的(即有没有相反数)。

  个人觉得时间复杂度是o(nlogn(排序)+nlogn(遍历+二分查找))。不过超时了qaq,3*10^5的数据量onlogn不应该超时呀(搞不懂)。

  代码贴上,题目出来了再补,不过希望不要是像6月模拟考那样的明明思路是对的,因为scanner读取超时,用bufferInputStream就ac了:

 1 import java.util.Scanner;
 2 import java.util.*;
 3 import java.io.*;
 4 public class Main {
 5     public static void main(String[] args) {
 6         Scanner in = new Scanner(System.in);
 7         while (in.hasNextInt()) {//注意while处理多个case
 8             int n = in.nextInt();
 9             int[] nums = new int[n];
10             int res = 0;
11             int zero = 0;
12             for(int i = 0; i < n;i++){
13                 String str = in.next();
14                 boolean flag = true;
15                 int len = str.length();
16                 for(int t = 0;t < len;t++){
17                     //if(c == '('){
18                     if(str.charAt(t) == '('){
19                         nums[i]++;
20                     }else{
21                         if(nums[i] <= 0 && flag){
22                             nums[i]-= 10000000;
23                         }
24                         nums[i]--;
25                     }
26                 }
27                 if(nums[i] == 0){
28                     zero++;
29                 }
30             }
31             Arrays.sort(nums);
32             //System.out.println(nums[0]);
33             for(int i = 0;i<n;i++){
34                 if(nums[i] > 0){
35                     res += find(nums,0,i,-nums[i]-10000000);
36                 }
37             }
38             System.out.println(res+zero*(zero-1)+zero);//结果是自身合法的数量+自身合法的两两结合+两个不合法的结合
39         }
40     }
41     static int find(int[] nums,int start,int end,int target){
42         int left = findl(nums,start,end,target);//找最左边
43         int right = findr(nums,start,end,target);//找最右边
44         return left == -1?0:(right-left+1);
45     }
46     static int findl(int[] nums,int start,int end,int target){
47         int mid;
48         while(start<=end){
49             mid = (start+end)/2;
50             if(mid >= 0 && mid <=end){
51                 if(nums[mid] == target){
52                     if(mid >= 1 && nums[mid-1] == target){//0 1 1(当前) 1
53                         end = mid - 1;
54                     }else{
55                         return mid;
56                     }
57                 }else if(nums[mid] < target){
58                     start = mid+1;
59                 }else if(nums[mid] > target){
60                     end = mid -1;
61                 }
62             }else{
63                 return -1;
64             }
65         }
66         return -1;
67     }
68     static int findr(int[] nums,int start,int end,int target){
69         int mid;
70         while(start<=end){
71             mid = (start+end)/2;
72             if(mid >= 0 && mid <=end){
73                 if(nums[mid] == target){
74                     if(mid < end && nums[mid+1] == target){//1 1(当前) 1 2
75                         start = mid + 1;
76                     }else{
77                         return mid;
78                     }
79                 }else if(nums[mid] < target){
80                     start = mid + 1;
81                 }else if(nums[mid] > target){
82                     end = mid -1;
83                 }
84             }else{
85                 return -1;
86             }
87         }
88         return -1;
89     }
90 }

  多说一句,不用二分查找target也是60%(qaq),有点怀疑自己撸的是假代码。

  等一个更新……(未完)

猜你喜欢

转载自www.cnblogs.com/zzzdp/p/9338898.html