常见机试题分析Java版
1. 操作系统任务分为系统任务和用户任务两种。其中,系统任务的优先级<50,用户任务的优先级>=50且<=255.优先级大于255的为非法任务,应予以剔除。现有一任务队列task[],长度为n,task中的元素值表示任务的优先级,数值越小,优先级越高。函数scheduler实现如下功能,将task[]种的任务按照系统任务、用户任务依次存放到system_task[]数组和user_task[]数组中,数组中元素的值是任务在task[]数组中的下标,并且优先级高的任务排在前面,优先级相同的任务按照入队顺序排列,数组元素为-1表示结束。例如:task[]={0,30,155,1,80,300,170,40,99} system_task[]=}0,3,1,7,-1} user_task[]={4,8,2,6,-1}。函数接口为void scheduler(int task[],int n,int system_task[],int user_task[])。
思路分析:
(1)先看给定的函数接口,参数为任务队列数组、任务数、系统任务数组和用户队列数组,也就是说在main函数中调用该函数时,这些参数是已经初始化了的。这里系统任务数组和用户队列数组就要注意了,题目中说数组元素为-1表示结束,即数组中并不是所有元素都是任务下标,输出时用一个while循环判断一下不是-1就成。那就好办了,先按照任务数组的长度初始化系统任务数组和用户队列数组,Java会自动为它们赋初值为0,这样就可以传参了。
(2)题目的核心是根据数组元素值的大小排列其下标,艾玛这不就是为HashMap量身定制的么。可以遍历任务队列,将系统任务和用户任务及其下标分别存入HashMap,然后对这两个HashMap分别按照值排序,再取出其键分别存入系统任务数组和用户任务数组,最后两个数组都添个-1就搞定了。
代码如下:
package cn.edu.xidian.crytoll; import java.util.*; import java.util.Map.*; public class Scheduler { public static void scheduler(int task[],int n,int system_task[],int user_task[]){ Map<Integer,Integer> inputsystem = new HashMap<Integer,Integer>(); Map<Integer,Integer> inputuser = new HashMap<Integer,Integer>(); for(int i=0;i<n;i++){ if(task[i]>=0&&task[i]<50) inputsystem.put(i,task[i]); else if(task[i]>=50&&task[i]<=255) inputuser.put(i,task[i]); } Map<Integer, Integer> outputsystem = sortByValue(inputsystem); Map<Integer, Integer> outputuser = sortByValue(inputuser); Set<Integer> systemset = outputsystem.keySet(); Set<Integer> userset = outputuser.keySet(); int systemn=0; int usern=0; for (Integer s:systemset) { system_task[systemn]=s; systemn++; } for (Integer s:userset) { user_task[usern]=s; usern++; } system_task[systemn]=-1; user_task[usern]=-1; int i=0; while(system_task[i]!=-1){ System.out.println(system_task[i]); ++i; } int j=0; while(user_task[j]!=-1){ System.out.println(user_task[j]); ++j; } } public static <K, V extends Comparable<V>> Map<K, V> sortByValue( Map<K, V> map) { List<Entry<K, V>> list = new LinkedList<Entry<K, V>>(map.entrySet()); Collections.sort(list, new Comparator<Entry<K, V>>() { public int compare(Entry<K, V> o1, Entry<K, V> o2) { Comparable<V> v1 = o1.getValue(); V v2 = o2.getValue(); if (v1 == null) { if (v2 == null) { return 0; } else { return -1; } } else { if (v2 == null) { return 1; } else { return v1.compareTo(v2); } } } }); Map<K, V> result = new LinkedHashMap<K, V>(); Iterator<Entry<K, V>> it = list.iterator(); while (it.hasNext()) { Entry<K, V> entry = it.next(); result.put(entry.getKey(), entry.getValue()); } return result; } public static void main(String[] args){ int task[]={0,30,155,1,80,300,170,40,99}; int n=task.length; int system_task[]=new int[n]; int user_task[]=new int[n]; scheduler(task,n,system_task,user_task); } }
2. 输入一个表达式,没有括号,数字小于0-9之间,输出计算结果,所有的中间结果化为整形。例如: 输入:3+8×2/9-2。输出:2
思路分析:
(1)输入的表达式是个字符串类型,要获取它的每个运算数和运算符需要用到charAt()方法。然后挨个字符地存入ArrayList,再使用get()方法遍历字符串。
(2)四则表达式的运算符分两种优先级,需遍历两次,第一次处理乘法和除法,第二次处理加法和减法。遇到运算符后将其前后两个数的运算结果求出,然后使用add()方法将运算结果插入到前运算数的位置,再连续使用remove()方法将参与此次运算的运算符和两个运算数移除。最后ArrayList中只剩一个元素,即为该表达式的值。使用parseInt()方法将其格式化后返回。
代码如下:
package cn.edu.xidian.crytoll; import java.util.ArrayList; import java.util.List; public class getMyRet { public int getMyRet(String str){ int len=str.length(); List<String> list=new ArrayList<String>(); for(int i=0;i<len;i++) list.add(str.charAt(i)+""); for(int j=0;j<list.size();j++){ if(list.get(j).equals("×")){ int ji=Integer.parseInt(list.get(j-1))*Integer.parseInt(list.get(j+1)); list.add(j-1,ji+""); list.remove(j); list.remove(j); list.remove(j); j--; } else if(list.get(j).equals("/")){ int shang=Integer.parseInt(list.get(j-1))/Integer.parseInt(list.get(j+1)); list.add(j-1,shang+""); list.remove(j); list.remove(j); list.remove(j); j--; } } for(int k=0;k<list.size();k++){ if(list.get(k).equals("+")){ int he=Integer.parseInt(list.get(k-1))+Integer.parseInt(list.get(k+1)); list.add(k-1,he+""); list.remove(k); list.remove(k); list.remove(k); k--; } if(list.get(k).equals("-")){ int cha=Integer.parseInt(list.get(k-1))-Integer.parseInt(list.get(k+1)); list.add(k-1,cha+""); list.remove(k); list.remove(k); list.remove(k); k--; } } int sum=Integer.parseInt(list.get(0)); return sum; } public static void main(String[] args){ String input="3+8×2/9-2"; getMyRet getmyret=new getMyRet(); System.out.println(getmyret.getMyRet(input)); } }
3. 将一个十进制(byte型)转换为二进制,将二进制数前后颠倒,再算出颠倒后对应的十进制数。
思路分析:进制互转的话Java有现成的方法可以调用。十进制转二进制用Integer类的toBinaryString()方法,二进制转十进制用Integer类的valueOf()方法。
代码如下:
package cn.edu.xidian.crytoll; public class UpperToLower { //遍历字符串中的每个字符,如果是小写则直接添加进结果字符串 //若是A-U的大写字母,将其转换成小写字母后加5,添加进结果字符串 //若是V-Z的大写字母,将其转换成小写字母后减21,添加进结果字符串 public String uptolow(String input){ String output=""; int len=input.length(); for(int i=0;i<len;i++){ if((input.charAt(i)+"").matches("[a-z]")) output=output+input.charAt(i); if((input.charAt(i)+"").matches("[A-U]")) output=output+((char)(input.charAt(i)+5)+"").toLowerCase(); if((input.charAt(i)+"").matches("[V-Z]")) output=output+((char)(input.charAt(i)-21)+"").toLowerCase(); } return output; } public static void main(String[] args){ String input="AbCdEfGhIjKlMnOpQrStUvWxYz"; System.out.println(new UpperToLower().uptolow(input)); } }
4. 输入一串数字,将第一个数字作为容量大小,从其它的数字中挑选出之和正好等于第一个数字的数字组合,若存在这样的数字组合其和等于第一个数字的大小,则输出1, 否则输出0。
输入:10,5,3,4,2(大体上是这种形式的)输出:1
思路分析:
(1)先将输入格式化,第一个数字拿出来作为目标和,其余数字存入数组并升序排序
(2)建立两个链表,一个用于存储备选数字,一个用于存储当前纳入选择的数字
(3)将备选数字存入链表,为其设置迭代器,因为是双层循环,故需创建一个迭代器副本
(4)设置已选数字的和并初始化为0,从第一个备选数字开始,清空已有和,比较当前数字数字与其他每个数字的和的情况
(5)若第一个备选数字和目标和相等,则返回1;若第一个备选数字大于目标和,则返回0;若当前备选数字小于目标和,判断当前备选数字和已有和相加是否等于目标和,若等于则直接返回1;若当前备选数字和已有和相加小于目标和,将当前备选数字填入已选列表,更新当前和;若当前备选数字和已有和相加大于目标和,若减去之前插入已选列表的数字正好等于目标和,则返回1;若减去之后小于目标和,则更新当前和及已选列表,跳出循环和下一个数相比;若减去之后还大于目标和,就得不断从已选列表中剔除最新插入的数字并更新当前和,直到当前和小于或等于目标和为止
代码如下:
package cn.edu.xidian.crytoll; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.List; public class IsEqual { public int isequal(String input){ //将输入存入字符串型数组 String[] all=input.split(","); //获取第一个数字作为目标和 int needsum=Integer.parseInt(all[0]); //将备选数字存入整型数组 int[] member=new int[all.length-1]; for(int i=0;i<member.length;i++) member[i]=Integer.parseInt(all[i+1]); //对备选数字数组排序 Arrays.sort(member); //建立两个链表,一个存储备选数字,一个存储当前纳入选择的数字 List<Integer> list=new LinkedList<Integer>(); List<Integer> content=new LinkedList<Integer>(); //将备选数字存入链表,为其设置迭代器,因为是双层循环,故需创建一个迭代器副本 for(int i=0;i<member.length;i++) list.add(member[i]); Iterator it=list.iterator(); Iterator it0=it; //设置已选数字的和并初始化为0 int sum=0; //从第一个备选数字开始,比较每一个数字与其他每个数字的和的情况 while(it.hasNext()){ it0=it; sum=0; while(it0.hasNext()){ int temp=(int)it0.next(); //若第一个备选数字和目标和相等,则返回1 if(temp==needsum) return 1; //若第一个备选数字大于目标和,则返回0 if(temp>needsum) return 0; //若当前备选数字小于目标和 if(temp<needsum){ //判断当前备选数字和已有和相加是否等于目标和,若等于则直接返回1 if(temp+sum==needsum) return 1; //若当前备选数字和已有和相加小于目标和,将当前备选数字填入已选列表,更新当前和 if(temp+sum<needsum){ content.add(temp); sum=sum+temp; } //若当前备选数字和已有和相加大于目标和, else if(temp+sum>needsum){ while(content.size()>1){ //若减去之前插入已选列表的数字正好等于目标和,则返回1 if(temp+sum-content.get(content.size()-1)==needsum) return 1; //若减去之后小于目标和,则更新当前和,已选列表,跳出循环和下一个数相比 if(temp+sum-content.get(content.size()-1)<needsum){ sum=sum-content.get(content.size()-1)+temp; content.remove(content.size()-1); content.add(temp); break; } //若减去之后还大于目标和,就得不断从已选列表中剔除最新插入的数字并更新当前和,直到当前和小于或等于目标和为止 else if(temp+sum-content.get(content.size()-1)>needsum){ sum=sum-content.get(content.size()-1); content.remove(content.size()-1); } } } } } } return 0; } public static void main(String[] args){ String input="10,5,3,4,2"; System.out.println(new IsEqual().isequal(input)); } }
5. 在给定字符串中找出单词( “单词”由大写字母和小写字母字符构成,其他非字母字符视为单词的间隔,如空格、问号、数字等等;另外单个字母不算单词);找到单词后,按照长度进行降序排序,(排序时如果长度相同,则按出现的顺序进行排列),然后输出到一个新的字符串中;如果某个单词重复出现多次,则只输出一次;如果整个输入的字符串中没有找到单词,请输出空串。输出的单词之间使用一个“空格”隔开,最后一个单词后不加空格。
思路分析:
(1)将单词门存入字符串型数组
(2)对inputs进行稳定的冒泡降序排序
(3)将长度大于一的单词加入结果字符串
代码如下:
package cn.edu.xidian.crytoll; import java.util.HashMap; import java.util.Map; public class MyWord { public String myword(String input,String output){ int len=input.length(); String temp=""; //将单词门存入字符串型数组 for(int i=0;i<len;i++){ if((input.charAt(i)+"").matches("[a-zA-Z]")) temp=temp+input.charAt(i); if(!(input.charAt(i)+"").matches("[a-zA-Z]")) temp=temp+" "; } String[] inputs=temp.split("\\s+"); //对inputs进行稳定的冒泡降序排序 for(int i=0;i<inputs.length-1;i++){ for(int j=0;j<inputs.length-i-1;j++){ if(inputs[j].length()<inputs[j+1].length()){ String tempstr=inputs[j]; inputs[j]=inputs[j+1]; inputs[j+1]=tempstr; } } } //将长度大于一的单词加入结果字符串 for(int i=0;i<inputs.length;i++){ if(inputs[i].length()>1&&output.indexOf(inputs[i])<0) output=output+inputs[i]+" "; } return output; } public static void main(String[] args){ String input="DING Zhongli, academician of the Chinese Academy of Sciences (CAS) and a test"; String output=""; System.out.println(new MyWord().myword(input, output)); } }