华为机试算法思路总结
本文主要是记录一下自己的思路。如果有不对的地方,希望大家多多指正。
刷题地址
https://www.nowcoder.com/ta/huawei
算法思路
求最小公倍数
题目地址
题目要求
题目描述
正整数A和正整数B 的最小公倍数是指 能被A和B整除的最小的正整数值,设计一个算法,求输入A和B的最小公倍数。
输入描述:
输入两个正整数A和B。
输出描述:
输出A和B的最小公倍数。
示例1
输入
5 7
输出
35
解题思路
最小公倍数=两数之积/两个数的最大公约数
实现代码
import java.util.Scanner;
public class Main {
public static int y(int a, int b) {
if (a < b) {
int tmp;
tmp = a;
a = b;
b = tmp;
}
int k;
while(b != 0) {
k = a % b;
a = b;
b = k;
}
return a;
}
public static void main(String args[]) {
Scanner reader = new Scanner(System.in);
while(reader.hasNext()){
int m = reader.nextInt();
int n = reader.nextInt();
System.out.println(m * n / y(m, n));
}
}
}
字符逆序
题目地址
题目要求
题目描述
将一个字符串str的内容颠倒过来,并输出。str的长度不超过100个字符。 如:输入“I am a student”,输出“tneduts a ma I”。
输入参数:
inputString:输入的字符串
返回值:
输出转换好的逆序字符串
输入描述:
输入一个字符串,可以有空格
输出描述:
输出逆序的字符串
示例1
输入
复制
I am a student
输出
tneduts a ma I
解题思路
将字符串转换成char[],对数组进行转换。1<->n,2<->n-1等等。
实现代码
import java.util.Scanner;
public class Main {
public static String revert(String str) {
char[] ss = str.toCharArray();
int j = ss.length / 2;
for (int i = 0; i < j; i++) {
char tmp = ss[i];
ss[i] = ss[ss.length - 1 - i];
ss[ss.length -1 - i] = tmp;
}
return new String(ss);
}
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String str = sc.nextLine();
System.out.println(revert(str));
// StringBuilder sb = new StringBuilder(str);
// System.out.println(sb.reverse().toString());
}
}
}
字符统计
题目地址
题目要求
题目描述
如果统计的个数相同,则按照ASCII码由小到大排序输出 。如果有其他字符,则对这些字符不用进行统计。
实现以下接口:
输入一个字符串,对字符中的各个英文字符,数字,空格进行统计(可反复调用)
按照统计个数由多到少输出统计结果,如果统计的个数相同,则按照ASII码由小到大排序输出
清空目前的统计结果,重新统计
调用者会保证:
输入的字符串以‘\0’结尾。
输入描述:
输入一串字符。
输出描述:
对字符中的
各个英文字符(大小写分开统计),数字,空格进行统计,并按照统计个数由多到少输出,如果统计的个数相同,则按照ASII码由小到大排序输出 。如果有其他字符,则对这些字符不用进行统计。
示例1
输入
aadddccddc
输出
dca
解题思路
将字符串转换成字符数组,遍历数组对字符进行统计,将结果放入map,对map的entrySet进行倒序排序。
代码实现
import java.util.*;
public class Main {
public static ArrayList<Map.Entry<Character, Integer>> getStrList(String str) {
if (str == null) {
return null;
}
HashMap<Character , Integer> map = new HashMap<>();
char[] ss = str.toCharArray();
int length = ss.length;
for (int i = 0; i < length; i++) {
char key = ss[i];
if (map.containsKey(key)) {
int num = map.get(key);
map.put(key, num + 1);
} else {
map.put(key, 1);
}
}
ArrayList<Map.Entry<Character, Integer>> list = new ArrayList<Map.Entry<Character, Integer>>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Character, Integer>>() {
@Override
public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {
if (o2.getValue().equals(o1.getValue())) {
return (((int)o1.getKey() > (int)o2.getKey())) ? 1 : -1;
}
return o2.getValue().compareTo(o1.getValue());
}
});
return list;
}
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str = sc.nextLine();
ArrayList<Map.Entry<Character, Integer>> list = getStrList(str);
for(Map.Entry<Character, Integer> mp : getStrList(str)){
System.out.print(mp.getKey());
}
System.out.println();
}
sc.close();
}
}
等差数列
题目地址
题目要求
题目描述
功能:等差数列 2,5,8,11,14。。。。
输入:正整数N >0
输出:求等差数列前N项和
返回:转换成功返回 0 ,非法输入与异常返回-1
本题为多组输入,请使用while(cin>>)等形式读取数据
输入描述:
输入一个正整数。
输出描述:
输出一个相加后的整数。
示例1
输入
复制
2
输出
复制
7
解题思路
等差数列求和公式:
(a1+an)n/2=(a1+a1+(n-1)d)n/2=a1n+n(n-1)*d/2
代码实现
import java.util.*;
// a1n+n(n-1)d/2
public class Main {
public static int getSum(int n) {
if (n < 0) {
return -1;
}
if (n == 1) {
return 2;
}
int sum = 2*n+n*(n-1)*3/2;
return sum;
}
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
System.out.println(getSum(n));
}
sc.close();
}
}
在字符串中找出连续最长的数字串
题目地址
题目要求
题目描述
样例输出
输出123058789,函数返回值9
输出54761,函数返回值5
接口说明
函数原型:
unsignedint Continumax(char** pOutputstr, char* intputstr)
输入参数:
char* intputstr 输入字符串;
输出参数:
char** pOutputstr: 连续最长的数字串,如果连续最长的数字串的长度为0,应该返回空字符串;如果输入字符串是空,也应该返回空字符串;
返回值:
连续最长的数字串的长度
输入描述:
输入一个字符串。
输出描述:
输出字符串中最长的数字字符串和它的长度。如果有相同长度的串,则要一块儿输出,但是长度还是一串的长度
示例1
输入
abcd12345ed125ss123058789
输出
123058789,9
解题思路
将字符串中的字符替换成“ ”,遍历数字数组,找出最长的数组,若相等,则拼接。
代码实现
import java.util.*;
public class Main {
static int max = 0;
public static String max(String str) {
if (str == null || str == "") {
return "";
}
String strnew = str.replaceAll("[a-zA-z]", " ");
String[] ss = strnew.split(" ");
max = ss[0].length();
String result = ss[0];
for (int i = 1; i < ss.length; i++) {
if (ss[i].length() > max) {
max = ss[i].length();
result = ss[i];
} else if (ss[i].length() == max) {
result += ss[i];
}
}
return result;
}
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str = sc.nextLine();
String result = max(str);
System.out.printf("%s,%d\n", result, max);
}
sc.close();
}
}
扑克牌大小
题目地址
题目要求
题目描述
扑克牌游戏大家应该都比较熟悉了,一副牌由54张组成,含3~A、2各4张,小王1张,大王1张。牌面从小到大用如下字符和字符串表示(其中,小写joker表示小王,大写JOKER表示大王):
3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER
输入两手牌,两手牌之间用"-“连接,每手牌的每张牌以空格分隔,”-"两边没有空格,如:4 4 4 4-joker JOKER。
请比较两手牌大小,输出较大的牌,如果不存在比较关系则输出ERROR。
基本规则:
(1)输入每手牌可能是个子、对子、顺子(连续5张)、三个、炸弹(四个)和对王中的一种,不存在其他情况,由输入保证两手牌都是合法的,顺子已经从小到大排列;
(2)除了炸弹和对王可以和所有牌比较之外,其他类型的牌只能跟相同类型的存在比较关系(如,对子跟对子比较,三个跟三个比较),不考虑拆牌情况(如:将对子拆分成个子);
(3)大小规则跟大家平时了解的常见规则相同,个子、对子、三个比较牌面大小;顺子比较最小牌大小;炸弹大于前面所有的牌,炸弹之间比较牌面大小;对王是最大的牌;
(4)输入的两手牌不会出现相等的情况。
输入描述:
输入两手牌,两手牌之间用"-“连接,每手牌的每张牌以空格分隔,”-"两边没有空格,如 4 4 4 4-joker JOKER。
输出描述:
输出两手牌中较大的那手,不含连接符,扑克牌顺序不变,仍以空格隔开;如果不存在比较关系则输出ERROR。
示例1
输入
4 4 4 4-joker JOKER
输出
joker JOKER
解题思路
若字符串包含“joker JOKER”,则输出“joker JOKER”
若两边牌数相等,则比较第一位,输出第一位大的那副牌
若两边牌数不相等,则检查是否有四位(炸弹),若有则输出炸弹牌,若没有,则输出”ERROR“
代码实现
import java.util.*;
public class Main {
public static String[] puke = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q",
"K", "A", "2", "joker", "JOKER"};
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str = sc.nextLine();
String[] inputs = str.split("-");
if (inputs.length != 2) {
System.out.println("ERROR");
return;
}
String[] left = inputs[0].split(" ");
String[] right = inputs[1].split(" ");
int leftNum = left.length;
int rightNum = right.length;
int leftFlag = 0;
int rightFlag = 0;
if (inputs[0].equals("joker JOKER") || inputs[1].equals("joker JOKER")) {
System.out.println("joker JOKER");
} else if (leftNum == rightNum) {
for (int i = 0; i < puke.length; i++) {
if (left[0].equals(puke[i])) {
leftFlag = i;
}
if (right[0].equals(puke[i])) {
rightFlag = i;
}
}
if (leftFlag > rightFlag) {
System.out.println(inputs[0]);
} else {
System.out.println(inputs[1]);
}
} else {
if (leftNum == 4) {
System.out.println(inputs[0]);
} else if (rightNum == 4) {
System.out.println(inputs[1]);
} else {
System.out.println("ERROR");
return;
}
}
}
}
}
求解立方根
题目地址
题目要求
题目描述
•计算一个数字的立方根,不使用库函数
详细描述:
•接口说明
原型:
public static double getCubeRoot(double input)
输入:double 待求解参数
返回值:double 输入参数的立方根,保留一位小数
输入描述:
待求解参数 double类型
输出描述:
输入参数的立方根 也是double类型
示例1
输入
216
输出
6.0
解题思路
二分法进行迭代,找到最接近的值。
xxx-y=0
代码实现
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
double input = sc.nextDouble();
double min = 0;
double max = input;
while (max - min > 0.0001) {
double tmp = (max + min) / 2;
if (tmp * tmp * tmp > input) {
max = tmp;
} else {
min = tmp;
}
}
min *= 10;
double small = min - (int)min;
if(small >= 0.5) {
min++;
}
int n = (int)min;
min = (double)n / 10;
System.out.println(min);
}
}
}
记负均正II
题目地址
题目要求
题目描述
从输入任意个整型数,统计其中的负数个数并求所有非负数的平均值,结果保留一位小数,如果没有非负数,则平均值为0
本题有多组输入数据,输入到文件末尾,请使用while(cin>>)读入
输入描述:
输入任意个整数
输出描述:
输出负数个数以及所有非负数的平均值
示例1
输入
-13
-4
-7
输出
3
0.0
解题思路
统计负数的个数c,和非负数共和s
非负数平均值=s/(总数-c)
代码实现
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String[] str = sc.nextLine().split(" ");
int c = 0;
int s = 0;
for (int i = 0; i < str.length; i++) {
int v = Integer.valueOf(str[i]);
if (v < 0) {
c++;
} else {
s += v;
}
}
double avg = 0;
if (str.length > c) {
avg = (double)s / (str.length - c);
}
System.out.println(c);
System.out.printf("%.1f\n", avg);
}
}
}
超长正整数相加
题目地址
题目要求
题目描述
请设计一个算法完成两个超长正整数的加法。
接口说明
/*
请设计一个算法完成两个超长正整数的加法。
输入参数:
String addend:加数
String augend:被加数
返回值:加法结果
*/
public String AddLongInteger(String addend, String augend)
{
/在这里实现功能/
return null;
}
输入描述:
输入两个字符串数字
输出描述:
输出相加后的结果,string型
示例1
输入
99999999999999999999999999999999999999999999999999
1
输出
100000000000000000000000000000000000000000000000000
解题思路
将输入的两个字符串先进行反转。
按位计算相同位置上的两个字符的和,放入StringBuffer中。字符相加规则:‘3’ + ‘0’ = 3
c.append(sum % 10); 取模获得本位上的数
r = sum / 10; 余数加入到下次循环中,即进位
最后将结果进行反转。
代码实现
import java.util.Scanner;
public class Main {
public static String AddLongInteger(String a, String b) {
StringBuffer c = new StringBuffer();
StringBuffer sa = new StringBuffer(a).reverse();
StringBuffer sb = new StringBuffer(b).reverse();
int N = Math.max(sa.length(), sb.length());
int r = 0;
for (int i = 0; i < N; i++) {
int bit1 = sa.length() > i ? sa.charAt(i) - '0' : 0;
int bit2 = sb.length() > i ? sb.charAt(i) - '0' : 0;
int sum = r + bit1 + bit2;
c.append(sum % 10);
r = sum / 10;
}
if (r > 0)
c.append(r);
return c.reverse().toString();
}
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
String a = sc.nextLine();
String b = sc.nextLine();
System.out.println(AddLongInteger(a, b));
}
sc.close();
}
}
判断一个数是否为质数
代码实现
public static boolean isPrimeNumber(int num) {
if (num == 2) {
return true;
}
if (num < 2 || num % 2 == 0) {
return false;
}
for (int i = 3; i < Mat.sqrt(num); i+=2) {
if (num % i == 0) {
return false;
}
}
return true;
}