牛客华为机试-查找排序

    技术2023-11-24  104

    前言:java编写,代码尽可能带注释,部分题目附上解题思路。力求方便,所以不写如有错误,请指出,谢谢。

    查找排序

    1、百钱买百鸡问题2、统计每个月兔子总数3、查找组成一个偶数最接近的两个素数4、公共字串计算5、成绩排序6、Redraiment的走法7、字符统计8、迷宫问题9、字符串排序10、质数因子11、自守数12、多线程

    1、百钱买百鸡问题

    题目描述 公元前五世纪,我国古代数学家张丘建在《算经》一书中提出了“百鸡问题”:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何? 详细描述: 接口说明 原型: int GetResult(vector &list) 输入参数: 无 输出参数(指针指向的内存区域保证有效): list 鸡翁、鸡母、鸡雏组合的列表 返回值: -1 失败 0 成功 import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNext() ){ int n = sc.nextInt(); // 将输入的1放入n,虽然没用 // n1、n2、n3分别表示吉翁、继母、鸡雏 int n1 = 0, n2 = 0, n3 = 0; //7x +4y = 100,两种思路:一、两层遍历;二、一层遍历 for(n1 = 0; n1 <=14; n1++ ){ for(n2 = 25; n2 >=0; n2--){ int sum = 7 * n1 + 4 * n2; if(sum == 100){ n3 = 100-n1-n2; System.out.println(n1 +" "+n2 + " "+n3); } } } for(n1 = 0; n1 <= 14; n1++){ double j; if(n1 == 0){ j = 25; }else{ j = (100-7*n1)/4.0; } if(Math.abs(j- Math.round(j)) < 1e-6){ n2 = (int)j; n3 = 100 - n1 - n2; System.out.println(n1 +" "+n2 + " "+n3); } } } } }

    2、统计每个月兔子总数

    题目描述 有一只兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子,假如兔子都不死,问每个月的兔子总数为多少? /** * 统计出兔子总数。 * * @param monthCount 第几个月 * @return 兔子总数 */ public static int getTotalCount(int monthCount) { return 0; } import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNext() ){ int month = sc.nextInt(); System.out.println(Main.getTotalCount(month)); } } // 统计兔子总数 public static int getTotalCount(int monthCount){ if(monthCount < 0) return 0; // 初始化三个月份的兔子 int oneMonthOld = 1; int twoMonthOld = 0; int threeMonthOld = 0; // 第一个月刚出生,所以月份要减一 for(int i = 0; i < monthCount-1; i++){ // 分别都长大一个月 threeMonthOld += twoMonthOld;// 三月份的兔子要加上从二月份发育过来的 twoMonthOld = oneMonthOld; oneMonthOld = threeMonthOld; } return oneMonthOld+twoMonthOld+threeMonthOld; } }

    3、查找组成一个偶数最接近的两个素数

    注:这里动态规划,比较不好懂

    题目描述 任意一个偶数(大于2)都可以由2个素数组成,组成偶数的2个素数有很多种情况,本题目要求输出组成指定偶数的两个素数差值最小的素数对 import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNext() ){ int even = sc.nextInt(); // 思路:从even/2向2查找质数,若另一个数也为质数满足条件 int max = even/2; for(int i = max; i >=2; i--){ if(Main.judge(i) && Main.judge(even-i)){ System.out.println(i); System.out.println(even-i); break; } } } } // 判断是否为质数 public static boolean judge(int number){ if(number <= 1){ return false; } for(int i = 2; i < number; i++){ // 若区间除了1和number外存在能整除number的数,则说明不是质数 if((number % i) == 0){ return false; } } return true; } }

    4、公共字串计算

    题目描述 题目标题: 计算两个字符串的最大公共字串的长度,字符不区分大小写 详细描述: 接口说明 原型: int getCommonStrLength(char * pFirstStr, char * pSecondStr); 输入参数: char * pFirstStr //第一个字符串 char * pSecondStr//第二个字符串 import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNext() ){ String str1 = sc.next(); String str2 = sc.next(); System.out.println(Main.getCommonStrLength(str1, str2)); } } // 常规解法 public static int getCommonStrLength(String str1, String str2){ // 空值判断以及空指针异常 if(str1 == null || str1.length() == 0 || str2 == null || str2.length()==0){ return 0; } int len1 = str1.length(); int len2 = str2.length(); int max = 0;// 初始化两个字符串的标志位,以及最大公共子串的长度 for(int i = 0; i < len1;){ for(int j = 0; j < len2;){ // 找到第一个重复的字符,试图遍历公共子串 if(str1.charAt(i) == str2.charAt(j)){ // 当出现相等时候,要保证后面一串尽可能相等,但需要找出最长的公共子串 // 出现相等则两个标志位一起走 int p1 = i, p2 = j; int count = 0; //System.out.println(p1 + " " + p2); while(p1 < len1 && p2 < len2 && str1.charAt(p1) == str2.charAt(p2)){ //System.out.println(""+str1.charAt(p1)); p1++; p2++; count++; } // 走完公共子串后保存最大长度 if(count > max){ max = count; } } //str2中当前字符与str1中当前字符不相等的,str2当前字符标志后移一位 j++; } // 遍历str2字符串都没找到与str1中当前字符相等,str1当前字符标志后移一位 i++; } return max; } // 动态规划的解法 public static int getCommonStrLength(String str1, String str2) { int len1 = str1.length(); int len2 = str2.length(); int[][] dp = new int[len1 + 1][len2 + 1];// 默认初始化为0 for (int i = 1; i <= len1; i++) { for (int j = 1; j <= len2; j++) { if (str1.charAt(i - 1) == str2.charAt(j - 1)) { // 两层遍历,找出每一次字符相等位置,若找到公共子串,那么在二维数组中走向将一直斜向下 dp[i][j] = dp[i - 1][j - 1] + 1; } } } int max = 0; for (int i = 0; i <= len1; i++) { for (int j = 0; j <= len2; j++) { if (max < dp[i][j]) max = dp[i][j]; } } return max; } }

    5、成绩排序

    注意:感觉同样分数同样成绩这里LinkedHashMap怕不合适吧

    题目描述 查找和排序 题目:输入任意(用户,成绩)序列,可以获得成绩从高到低或从低到高的排列,相同成绩 都按先录入排列在前的规则处理。 例示: jack 70 peter 96 Tom 70 smith 67 从高到低 成绩 peter 96 jack 70 Tom 70 smith 67 从低到高 smith 67 jack 70 Tom 70 peter 96 注:0代表从高到低,1代表从低到高 // 名字可能相同,分数可能相同,要想唯一键,则利用名字加分数 import java.util.*; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(sc.hasNext() ){ String name; Integer score; List<Integer> scoreList = new ArrayList<>(); Map<String, Integer> map = new LinkedHashMap<>(); // 存放score与name+" "+score的映射 int sortNum = sc.nextInt(); int sortMethod = sc.nextInt(); // 0 表示升序,1表示降序 for(int i = 0; i < sortNum; i++){ name = sc.next(); score = sc.nextInt(); scoreList.add(score); map.put(name+" "+score, score); } Collections.sort(scoreList); if(sortMethod == 0){ // 降序 Collections.reverse(scoreList); } int pre = -1; for(int s : scoreList){ if(pre == s){ // scoreList中不用查找重复值 continue; } for(String key : map.keySet()){ if(map.get(key).equals(s)){ // 第一次找到 System.out.println(key); } } pre = s; } } } }

    6、Redraiment的走法

    注意:最长递增序列

    题目描述 Redraiment是走梅花桩的高手。Redraiment总是起点不限,从前到后,往高的桩子走,但走的步数最多,不知道为什么?你能替Redraiment研究他最多走的步数吗? 样例输入 6 2 5 1 5 4 5 样例输出 3 提示 Example: 6个点的高度各为 2 5 1 5 4 5 如从第1格开始走,最多为3步, 2 4 5 从第2格开始走,最多只有1步,5 而从第3格开始走最多有3步,1 4 5 从第5格开始走最多有2步,4 5 所以这个结果是3。 import java.util.*; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); while (input.hasNextInt()) { int n = input.nextInt(); int[] a = new int[n]; for (int i = 0; i < n; i++) a[i] = input.nextInt(); System.out.println(getMaxSteps(a, n)); } } // 转化成求最长递增子序列 public static int getMaxSteps(int [] arr ,int n) { int[] dp = new int[n]; for(int i = 0; i < n; i++){ dp[i] = 1; for(int j = 0; j < i; j++){ if(arr[j] < arr[i]){ dp[i] = Math.max(dp[i], dp[j]+1); } } } // 遍历数组找出最大值 int max = 0; for(int i = 0; i < n; i++){ if(dp[i] > max){ max = dp[i]; } } return max; } }

    7、字符统计

    题目描述 如果统计的个数相同,则按照ASCII码由小到大排序输出 。如果有其他字符,则对这些字符不用进行统计。 实现以下接口: 输入一个字符串,对字符中的各个英文字符,数字,空格进行统计(可反复调用) 按照统计个数由多到少输出统计结果,如果统计的个数相同,则按照ASII码由小到大排序输出 清空目前的统计结果,重新统计 调用者会保证: 输入的字符串以‘\0’结尾。 package zTestDay; import java.util.*; public class Main { // 方法一,hashMap加treeMap public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { Map<Character, Integer> map = new HashMap<>(); String str = sc.next(); for(int i = 0; i < str.length(); i++){ Character key = str.charAt(i); // 只对英文字符,数字,空格统计 if((key >= '0' && key <= '9') || (key >= 'A' && key <='Z') || (key >= 'a' && key <='z') || key == ' '){ if(map.containsKey(key) ){ map.put(key, map.get(key)+1); }else{ map.put(key, 1); } } } Map<Integer, Character> treeMap = new TreeMap<>(); for(Character key :map.keySet()){ // 有相同次数key,无相同的val, 所以利用map的key与val构造treeMap新的唯一key treeMap.put(map.get(key) * 128 + 128 - key , key); // 这里必须是-key,才能使得出现相同的次数的字母按照assic降序排列 } StringBuilder sb = new StringBuilder(); for(Integer i : treeMap.keySet()){ sb.append(treeMap.get(i)); } System.out.println(sb.reverse().toString()); } } // 方法二、treeMap与次数降序查找,能够运用主要是因为字符最多256 public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { Map<Character, Integer> map = new TreeMap<>(); // 必须用treeMap Set<Integer> set = new HashSet<>(); String str = sc.next(); for(int i = 0; i < str.length(); i++){ Character key = str.charAt(i); // 只对英文字符,数字,空格统计 if((key >= '0' && key <= '9') || (key >= 'A' && key <='Z') || (key >= 'a' && key <='z') || key == ' '){ if(map.containsKey(key) ){ map.put(key, map.get(key)+1); }else{ map.put(key, 1); } set.add(map.get(key)); // 保存出现的次数,去重 } } List<Integer> count = new ArrayList<>(); for(Integer i :set){ count.add(i); } Collections.reverse(count); // 将出现次数降序 StringBuilder sb = new StringBuilder(); for(Integer i : count){ for(Character key : map.keySet()){ // 这里hashmap里面存储字符,所以数据不会太多,要不然不能两层循环 if(map.get(key) == i){ sb.append(key); } } } System.out.println(sb.toString()); } } }

    8、迷宫问题

    题目描述 定义一个二维数组N*M(其中2<=N<=10;2<=M<=10),如5 × 5数组下所示: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。入口点为[0,0],既第一空格是可以走的路。 Input 一个N × M的二维数组,表示一个迷宫。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。 Output 左上角到右下角的最短路径,格式如样例所示。 Sample Input 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0 Sample Output (0, 0) (1, 0) (2, 0) (2, 1) (2, 2) (2, 3) (2, 4) (3, 4) (4, 4) import java.util.LinkedList; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(sc.hasNext()){ int rows = sc.nextInt(); int cols = sc.nextInt(); int[][] maze = new int[rows][cols]; // 0表示未访问,1表示以访问,-1表示无法访问 for(int i = 0; i < rows; i++){ for(int j = 0; j < cols; j++){ int val = sc.nextInt(); if(val == 1){ maze[i][j]=-1; } } } //System.out.println(rows+" "+ cols); LinkedList<String> list = new LinkedList<>(); findRoute(maze, 0, 0, rows, cols, list); for(String step : list){ System.out.println(step); } } } private static boolean findRoute(int[][] maze, int i, int j, int rows, int cols, LinkedList<String> list) { if(i >= 0 && j >= 0 && i < rows && j < cols && maze[i][j] == 0){ // 能访问(i,j)这位置 maze[i][j] = 1; list.add("("+i+","+j+")"); if(i == rows-1 && j == cols-1){ // 已经找到了出口点 return true; } if(findRoute(maze, i+1, j, rows, cols, list) || findRoute(maze, i-1, j, rows, cols, list) || findRoute(maze, i, j+1, rows, cols, list) || findRoute(maze, i, j-1, rows, cols, list)){ // 能继续访问下一步 return true; }else{ // 恢复未访问的状态 maze[i][j] = 0; list.removeLast(); return false; } }else{ // 不能访问此位置 return false; } } }

    9、字符串排序

    注:思路不够简洁

    题目描述 编写一个程序,将输入字符串中的字符按如下规则排序。 规则 1 :英文字母从 A 到 Z 排列,不区分大小写。 如,输入: Type 输出: epTy 规则 2 :同一个英文字母的大小写同时存在时,按照输入顺序排列。 如,输入: BabA 输出: aABb 规则 3 :非英文字母的其它字符保持原来的位置。 如,输入: By?e 输出: Be?y import java.util.*; // 利用treeMap的键排序,利用hashMap保存位置映射关系 public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { String input = sc.nextLine(); TreeMap<Character, String> map = new TreeMap<>(); // 利用treemap的key排序, //ArrayList<Character> list = new ArrayList<>(); HashMap<Integer, Character> hashMap = new HashMap<>(); // 非英文字母位置映射 for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); // 字符 if (Character.isLetter(c)) { // 字符为字母 char lower = Character.toLowerCase(c); if (map.containsKey(lower)) { map.put(lower, map.get(lower) + c); // 将小写字母作为key,小写后相同的字母按顺序排列为value } else { map.put(lower, c + ""); } //list.add(c); // 列表添加字符 } else { // 若字符不为字母,保存位置映射关系 hashMap.put(i, c); } } // 这里同时可以利用集合排序,那么也不需要利用hashMap保存非字母位置,遍历输入字符串,非字母字符位置就知道了 /* Collections.sort(list, new Comparator<Character>() { @Override public int compare(Character o1, Character o2) { return Character.toLowerCase(o1) - Character.toLowerCase(o2); } });*/ StringBuilder sb = new StringBuilder(); // 存储字符为字母的数组,并按照小写字母排序 for (Character key : map.keySet()) { sb.append(map.get(key)); } StringBuilder sb2 = new StringBuilder(); int i = 0, j = 0; while (i < input.length()) { if (hashMap.containsKey(i)) { sb2.append(hashMap.get(i)); } else if (j < sb.length()) { sb2.append(sb.charAt(j++)); } i++; } System.out.println(sb2.toString()); } } }

    10、质数因子

    题目描述 功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 ) 最后一个数后面也要有空格 import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { Long input = sc.nextLong(); ArrayList<Integer> list = new ArrayList<>(); int n = 2; while(input >= 2){ if(input % n == 0){ // 若能整除,添加质数因子 input = input / n; list.add(n); }else{ // 找下一个质数 //n = getNext(n); n++; // 这里压根不需要找下一个质数,而是加一就行,和质数定义有关 } } for(Integer i : list){ System.out.print(i + " "); } } } // 找出下一位质数 private static int getNext(int n) { while(true){ n++; if(judge(n)){ return n; } } } // 判断是否为质数 private static boolean judge(int n) { for(int i = 2; i < n; i++){ if(n % i == 0){ return false; } } return true; } }

    11、自守数

    题目描述 自守数是指一个数的平方的尾数等于该数自身的自然数。 例如:25^2 = 625,76^2 = 5776,9376^2 = 87909376。请求出n以内的自守数的个数 import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { Long input = sc.nextLong(); int cnt = 1; for(int i = 1; i <= input; i++){ // 0 也算自守数 if(judge(i)){ cnt++; } } System.out.println(cnt); } } // 判断是否自守数 private static boolean judge(long i) { int count = 1; // 统计是几位数 if(i <= 0) return false; while(i >= (long)Math.pow(10, count)){ count++; } long square = i * i; long divisor = (long)Math.pow(10, count); //若尾数部分全部相同,相减后整除10次方位数,如25就是两位数,除以100 if((square - i) % divisor == 0){ return true; } return false; } }

    12、多线程

    注意:牛客上看到的通过案列Java不对,只能本地通过,牛客不通过

    题目描述 问题描述:有4个线程和1个公共的字符数组。线程1的功能就是向数组输出A,线程2的功能就是向字符输出B,线程3的功能就是向数组输出C,线程4的功能就是向数组输出D。要求按顺序向数组赋值ABCDABCDABCD import java.util.Scanner; public class Main { public static void main(String[] args) throws Exception{ Object a = new Object(); Object b = new Object(); Object c = new Object(); Object d = new Object(); Scanner sc = new Scanner(System.in); while (sc.hasNext()){ int count = sc.nextInt(); Runnable pa = new MyRunnable("A", d, a, count); Runnable pb = new MyRunnable("B", a, b, count); Runnable pc = new MyRunnable("C", b, c, count); Runnable pd = new MyRunnable("D", c, d, count); new Thread(pa).start(); Thread.sleep(1); new Thread(pb).start(); Thread.sleep(1); new Thread(pc).start(); Thread.sleep(1); new Thread(pd).start(); } } } class MyRunnable implements Runnable{ private String name; private Object prev; private Object self; private int count; MyRunnable(String name, Object prev, Object self, int count) { this.name = name; this.prev = prev; this.self = self; this.count = count; } @Override public void run() { // int count = 10; while (count > 0) { synchronized (prev){ synchronized (self){ System.out.print(name); count--; self.notify(); } try { prev.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
    Processed: 0.015, SQL: 9