第一题:二进制插入二进制插入__牛客网
给定32位整数n和m,同时我们指定i和j,将m的二进制位数插入到n的二进制位数的j到i位,我们保证n的j到i位均是等于0的,况且m的二进制位数小于等于i-j+1,其中二进制的位数从0开始从低到高
测试样例:
1024,19,2,6
返回:1100
思路:
1)我们先来进行分析一下这道题:n=1024,m=19
我们先把m的二进制位数先写出来,那么就是:10000000000
我接下来把n的二进制位数都写出来,那么就是:10011
2)另外在题目中已经说过了,我们要进行插入的目标位置一定是都是等于0的
import java.util.*; public class BinInsert { public int binInsert(int n, int m, int begin, int end) { for(int i=0;i<begin;i++){ m=m<<1; } int result=m|n; return result; } }
笔试题2:查找组成一个偶数最接近的两个素数查找组成一个偶数最接近的两个素数_牛客题霸_牛客网
第一种思路:我们期望的是定义一个下标i从前向后进行遍历,进行遍历的结束位置是小于等于index/2,我们边进行遍历边进行判断index-i-i的值是否小于我们之前的最大值
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static Boolean IsPrime(int data){ for(int i=2;i<=data/2;i++){ //注意我们这里面的截止条件是不能是Math.sqrt(data)的值,因为比如说输入一个13,最终输出的应该是6和7,但是最后会进行输出2和11,也就是说最终根本走不到6和7的位置 if(data%i==0){ return false; } } return true; } public static void main(String[] args) { Scanner scanner=new Scanner(System.in); while(scanner.hasNext()){ int index=scanner.nextInt(); int min=Integer.MAX_VALUE; int[] array=new int[2]; for(int i=2;i<=index/2;i++){ if(IsPrime(i)&&IsPrime(index-i)){ int result=index-i-i; if(result<=min){ min=result; array[0]=i; array[1]=index-i; } } } System.out.println(array[0]); System.out.println(array[1]); } } }
第二种思路:我们从这个数的中间位置向前开始进行遍历
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static boolean IsPrime(int data){ for(int i=2;i<=Math.sqrt(data);i++){ if(data%i==0){ return false; } } return true; } public static void main(String[] args) { Scanner scanner=new Scanner(System.in); int result=scanner.nextInt(); for(int i=result/2;i>1;i--){ if(IsPrime(i)&&IsPrime(result-i)){ System.out.println(i); System.out.println(result-i); break; } } } }
笔试题三.参数解析: 参数解析_牛客题霸_牛客网
中心思路:
1)当我们遇到双引号的时候,我们要一直向后进行遍历直到遇到第二个双引号
2)我们本质上是在使用StringBuilder来进行拼接
import java.util.*; public class Main { public static void main(String[] args) { Scanner scanner=new Scanner(System.in); String s=scanner.nextLine(); //1.我们先进行统计整个字符串按照空格分割之后字符串的个数 int i=0; int count=0; while(i<s.length()){ if(s.charAt(i)==' '){ count++; } if(s.charAt(i)=='"'){ i++; while(i<s.length()&&s.charAt(i)!='"'){ i++; } //循环退出之后,我们此时的i下标此时指向了"位置,此时我们应该让i在进行++一下 } i++; } System.out.println(count+1); i=0; //2我们开始进行分个字符 StringBuilder sb=new StringBuilder(); while(i<s.length()){ if(s.charAt(i)==' '){ sb.append("\n"); i++; }else{ if(s.charAt(i)=='"'){ i++; while(i<s.length()&&s.charAt(i)!='"'){ sb.append(s.charAt(i)); i++; } i++; }else{ sb.append(s.charAt(i)); i++; } } } System.out.println(sb); } }
思路2:我们可以使用flag值来进行做标记,我们默认情况下flag的值是1,但是说如果遇到第一个",那么我们就将flag置为0,遇到第二个",我们就将flag置为1
异或思路:相同为0,不同为1
import java.util.*; public class Main { public static void main(String[] args) { //1.我们先进行统计所有单词的个数 Scanner scanner=new Scanner(System.in); String str=scanner.nextLine(); int count=0; int i=0; while(i<str.length()){ if(str.charAt(i)==' '){ count++; } //我们遇到左",我们就一直向后进行遍历,直到遇到第二个" if(str.charAt(i)=='"'){ i++; while(i<str.length()&&str.charAt(i)!='"'){ i++; } //说明此时i指向了第二个",我们此时就应该让i继续向后++操作 } i++; } System.out.println(count+1); //2.我们在进行尝试打印所有空格 i=0; int flag=1; for(i=0;i<str.length();i++){ if(str.charAt(i)=='"'){ flag=flag^1; } //除了双引号里面的空格和双引号,其他都进行输出 if(str.charAt(i)!=' '&&str.charAt(i)!='"'){ System.out.print(str.charAt(i)); } //双引号里面的空格我们要进行特殊处理 if(str.charAt(i)==' '&&flag==0){ System.out.print(" "); } //我们如果遇到双引号之外的空格根本就不需要进行输出,直接打印一个换行就可以了 if(str.charAt(i)==' '&&flag==1){ System.out.println(); } } } }
笔试题四:跳石板
题目叙述:我们的小易来到了一条石板路前面,每一块石板上面从1紧挨着编号为1,2,3.....这一条石板路需要特殊的规则才可以向前前进,对于当前小易所在的编号为K的石板,小易单次只能向前跳当前K的一个约数(不会包含1和K)步,即跳到K+X(X为K的一个非1和本身的约数的位置),小易当前处于编号为N的石板,他是想要进行跳转到编号恰好是M的石板上面去,小易想要知道至少要进行跳转几次才可以到达
例如说:N=4,M=24
4->6->8->12->18->24,于是小易至少要跳跃5次,就可以从4号石板跳转到24号石板
思路:
1)我们首先要进行想明白,从N->M肯定会有多种解法的,我们最终还是需要进行寻找一个最优解,因为就是说每一个对应的K值是由多个因子的,但是对应的一个K值本身和1是不可以被包含进来的
2)我们在这里面采取的思想就是动态规划,答案要在后面的问题要用到
3)我的思路就是说申请一个大小为N-M的数组,数组的下标代表我们当前的K值,数组的元素代表我们的当前的走的步数
import java.util.*; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { //求两个数的最小值 public static int GetMin(int s1,int s2){ if(s1>=s2) return s2; return s1; } //求一个数的约数 public static List<Integer> GetYu(int data){ List<Integer> list=new LinkedList<>(); for(int i=2;i<=data/2;i++){ if(data%i==0){ list.add(i); } } return list; } public static void main(String[] args) { //循环输入一个跳跃的起始位置和跳跃的终止位置 Scanner scanner=new Scanner(System.in); int N=scanner.nextInt(); int M=scanner.nextInt(); int[] array=new int[M+1]; //1.我们先进行初始化整个数组,数组的下标代表我们的K值,数组中的元素代表跳到次台阶上面的次数 也就是代表走的次数 for(int i=0;i<M+1;i++){ array[i]=-1; } array[N]=0; //2.开始进行走台阶 for(int i=N;i<M;i++){ if(array[i]==-1){ //说明当前台阶我们无法走到,所以进行回退 continue; } //这里面的step代表每一次可以跳几块石板,i代表当前石板的编号 List<Integer> result=GetYu(i); for(int step:result){ //如果当前数组的下标中已经存放了元素,那么我们要和新存入的和老的值进行比较 if(i+step<=M&&array[i+step]!=-1){ array[i+step]=GetMin(array[i+step],array[i]+1); //如果说当前数组的下标中没有存放元素还是初始化的默认值,那么我们就存放上一个元素+1 }else if(i+step<=M&&array[i+step]==-1){ array[i+step]=array[i]+1; } } } //如果遍历所有的下标导致最终的值最终还是等于-1,说明此事并没有步数走到这里 if(array[M]!=-1){ System.out.println(array[M]); }else{ System.out.println(-1); } } }