写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。
背景知识: 16进制以0x开头,后面跟数字0 ~ 9或字母A ~ F(小写也可以)
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String a = in.nextLine();
// 去掉表示十六进制的 0x 前缀 —— 从而使得我们可以使用下面的 API 实现进制转换
a = a.substring(2);
// 实现进制转换的两种 API
// int ans = Integer.valueOf(a, 16);
int ans = Integer.parseInt(a, 16);
System.out.println(ans);
}
思路很简单,就类似于给你一个 10 进制的字符串,如何整合成 10 进制数字 。 都是从后向前遍历,取出每一位,然后整合在一起。
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String a = in.next();
a = a.substring(2);
int n = a.length();
int ans = 0;
int base = 1;
for(int i=n-1; i>=0; i--){
// 当前位的值
int num;
// 取出当前位, 并且转为大写
int curChar = Character.toUpperCase(a.charAt(i));
if(curChar >= '0' && curChar <= '9'){
num = curChar - '0';
} else {
num = 10 + curChar - 'A';
}
ans += num * base;
base *= 16;
}
System.out.println(ans);
}
}
计算字符串最后一个单词的长度,单词以空格隔开,字符串长度小于5000。(注:字符串末尾不以空格为结尾)
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String a = in.nextLine();
int ans = 0;
int idx = a.length() - 1;
while(idx != -1 && a.charAt(idx) != ' '){
idx--;
ans++;
}
System.out.println(ans);
}
注: 为什么不用 split 法, 因为占用太多额外的空间了,所以不用 API 了 (虽然我是最懒懒喜欢用 API 的人,但是这种占用太多额外空间的,而且明显有更优解法的,咱就不用了)
开发一个坐标计算工具, A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动。从(0,0)点开始移动,从输入字符串里面读取一些坐标,并将最终输入结果输出到输出文件里面。
字符串类型题,主要考查点在于字符串处理函数,加上循序渐进的思考能力
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public boolean isEffective(String str) {
if(str.isEmpty() || str.length() > 3){
return false;
}
String direction = "ADWS";
if(direction.indexOf(str.charAt(0)) == -1) {
return false;
}
for(int i=1; i<str.length(); i++){
if(!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
public static void main(String[] args) {
Main main = new Main();
Scanner in = new Scanner(System.in);
String a = in.nextLine();
String[] strs = a.split(";");
int x = 0;
int y = 0;
for(String str : strs) {
// 先判断是否无效
if(!main.isEffective(str)){
continue;
}
// 有效进行处理
char direction = str.charAt(0);
int step = Integer.parseInt(str.substring(1));
if(direction == 'A'){
x -= step;
} else if(direction == 'D'){
x += step;
} else if(direction == 'W'){
y += step;
} else {
y -= step;
}
}
System.out.println(x + "," + y);
}
}
吐血 …
总结反思 : 没必要写这么长,没必要那么多标注位,拆成函数解决,就 ok 了
import java.util.Scanner;
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextLine()) {
String pas = in.nextLine();
if(pas.length() <= 8){
System.out.println("NG");
continue;
}
boolean over = false;
// 每位标志分别表示 大写字母,小写字母 , 数字, 其他符号
int[] flag = new int[4];
for(int i=0; i<pas.length(); i++){
char cur = pas.charAt(i);
if(cur == ' ' || cur == '\n' ){
over = true;
break;
}
if(Character.isDigit(cur)){
flag[0] = 1;
} else if(Character.isLowerCase(cur)){
flag[1] = 1;
} else if(Character.isUpperCase(cur)){
flag[2] = 1;
} else {
flag[3] = 1;
}
// 说明已经凑齐了
if(Arrays.stream(flag).sum() >= 3){
break;
}
}
// 包含空格和换行符,不满足题意
if(over){
System.out.println("NG");
continue;
}
// 没凑齐,是不满足题意的
if(Arrays.stream(flag).sum() < 3){
System.out.println("NG");
continue;
}
Set<String> set = new HashSet();
for(int i=0; i<pas.length()-1; i++){
for(int j=i+2; j<pas.length(); j++){
String subStr = pas.substring(i, j+1);
if(set.contains(subStr)){
over = true;
break;
}
set.add(subStr);
}
}
if(over){
System.out.println("NG");
} else {
System.out.println("OK");
}
}
}
}
原理:ip地址的每段可以看成是一个0-255的整数,把每段拆分成一个二进制形式组合起来,然后把这个二进制数转变成一个长整数。
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Main main = new Main();
Scanner in = new Scanner(System.in);
String ip = in.nextLine();
String numStr = in.nextLine();
System.out.println(main.IpToNum(ip));
System.out.println(main.NumToIp(Long.parseLong(numStr)));
}
// 数字转 Ip 地址
public String NumToIp(Long num){
// 转换为 二进制 字符串
String biNum = Long.toBinaryString(num);
int len = biNum.length();
// 用于拼接整合结果
StringBuilder sb = new StringBuilder();
for(int i=0; i<32-len; i++){
sb.append("0");
}
sb.append(biNum);
// 每八位加入一个 "."
sb.insert(8, ".");
sb.insert(17, ".");
sb.insert(26, ".");
String biAn = new String(sb);
String[] strs = biAn.split("\\.");
int[] reduce = Arrays.stream(strs).mapToInt(string -> Integer.parseInt(string, 2)).toArray();
String ans = "";
for(int i=0; i<4; i++){
ans += reduce[i];
if(i != 3){
ans += ".";
}
}
return ans;
}
public Long IpToNum(String ip){
String[] strs = ip.split("\\.");
String ans = "";
// 组合 ans
for(int i=0; i<4; i++){
String cur = strs[i];
int num = Integer.parseInt(cur);
String biNum = Integer.toBinaryString(num);
int zeroNums = 8 - biNum.length();
while(zeroNums > 0){
biNum = "0" + biNum;
zeroNums--;
}
ans += biNum;
}
// 把 ans 转为 10 进制
Long ansNum = Long.parseLong(ans, 2);
return ansNum;
}
}
矩阵乘法的运算量与矩阵乘法的顺序强相关。
例如:
A是一个50×10的矩阵,B是10×20的矩阵,C是20×5的矩阵
计算ABC有两种顺序:((AB)C)或者(A(BC)),前者需要计算15000次乘法,后者只需要3500次。
编写程序计算不同的计算顺序需要进行的乘法次数。
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int num = Integer.parseInt(in.nextLine());
int[][] arr = new int[num][2];
for(int i=0; i<num; i++){
String[] cur = in.nextLine().split(" ");
arr[i][0] = Integer.parseInt(cur[0]);
arr[i][1] = Integer.parseInt(cur[1]);
}
int ans = 0;
String str = in.nextLine();
Stack<int[]> stack = new Stack<>();
for(int i=0; i<str.length(); i++){
if(str.charAt(i) == '('){
// stack.push('(');
} else if(str.charAt(i) == ')'){
// 出栈,找到对应的右括号
int[] B = stack.pop();
int[] A = stack.pop();
ans += A[0] * A[1] * B[1];
// stack.pop();
// 放入计算结果
stack.push(new int[]{A[0], B[1]});
} else {
stack.push(arr[str.charAt(i)- 'A']);
}
}
System.out.println(ans);
}
}
注: 本题的关键在于 栈序列 最后输出的顺序 …
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
List<List<Integer>> ans = new ArrayList<>();
public static void main(String[] args) {
Main main = new Main();
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
int num = Integer.parseInt(in.nextLine());
String sort = in.nextLine();
String[] sortArr = sort.split(" ");
int[] pushArr = new int[num];
for (int i = 0; i < num; i++) {
pushArr[i] = Integer.parseInt(sortArr[i]);
}
List<Integer> list = new ArrayList<>();
boolean[] used = new boolean[num];
// 输出以字典序从小到大排序的火车出站序列号
List<String> ansString = new ArrayList<>();
// 得到所有组合数
main.getAll(num, pushArr, list, used);
for (int i = 0; i < main.ans.size(); i++) {
List<Integer> list1 = main.ans.get(i);
if (main.canGet(list1.stream().mapToInt(a -> a).toArray(), pushArr)) {
StringBuilder sb = new StringBuilder();
for (int k = 0; k < num; k++) {
sb.append(list1.get(k) + "");
if(k != num){
sb.append(" ");
}
}
ansString.add(String.valueOf(sb));
}
}
Collections.sort(ansString);
for(int i=0; i<ansString.size(); i++){
System.out.println(ansString.get(i));
}
}
public void getAll(int n, int[] arr, List<Integer> list, boolean[] used) {
if (list.size() == n) {
ans.add(new ArrayList<>(list));
return;
}
for (int i = 0; i < n; i++) {
if (!used[i]) {
used[i] = true;
list.add(arr[i]);
getAll(n, arr, list, used);
list.remove(list.size() - 1);
used[i] = false;
}
}
}
public boolean canGet(int[] popArr, int[] pushArr) {
// 用栈来进行模拟
Stack<Integer> stack = new Stack<>();
// j 表示当前遍历到的出栈位置
int j = 0;
for (int i = 0; i < pushArr.length; i++) {
stack.push(pushArr[i]);
while (!stack.isEmpty() && (j < popArr.length && stack.peek() == popArr[j]) ) {
stack.pop();
j++;
}
}
return stack.isEmpty();
}
}
将输入的字符串(字符串仅包含小写字母‘a’到‘z’)按照如下规则,循环转换后输出: a->b,b->c,…,y->z,z->a;
翻译
对连续的字母,奇数位置上的转换两次,偶数上的位置按照原始位置转换 1 次
思路
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 得到该字符串
String string = in.next();
char[] stringArr = string.toCharArray();
// 统一转换第一次
for (int i=0; i<stringArr.length; i++){
if(stringArr[i] == 'z'){
stringArr[i] = 'a';
} else {
stringArr[i] = (char) ((int)stringArr[i] + 1);
}
}
// 第二次遍历,对形如 aa 形式的再次转换,因为第三个出现的按照第一次的转换,所有直接跳 2
for (int i=1; i<stringArr.length; i++){
if(stringArr[i] == stringArr[i-1]) {
if(stringArr[i] == 'z'){
stringArr[i] = 'a';
} else {
stringArr[i] = (char) ((int)stringArr[i] + 1);
}
i += 1;
}
}
System.out.println(new String(stringArr));
}
给定 n 个字符串,请对 n 个字符串按照字典序排列。
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int length = in.nextInt();
String[] strs = new String[length];
int i = 0 ;
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNext()) { // 注意 while 处理多个 case
String a = in.next();
strs[i] = a;
i++;
}
Arrays.sort(strs);
for(int j=0; j<length; j++){
System.out.println(strs[j]);
}
}
}
查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。
注:子串的定义:将一个字符串删去前缀和后缀(也可以不删)形成的字符串。请和“子序列”的概念分开!
思路 :
动态规划
if(strs1[i] != strs2[j]){
dp[i][j] = 0;
} else {
dp[i][j] = dp[i-1][j-1] + 1;
}
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
String a = in.next();
String b = in.next();
int aLen = a.length();
int bLen = b.length();
if(aLen > bLen){
String temp = a;
a = b;
b = temp;
int tempNum = aLen;
aLen = bLen;
bLen = tempNum;
}
char[] aStr = a.toCharArray();
char[] bStr = b.toCharArray();
// dp 数组表示以 (i, j)结尾的相同子字符串的最长长度
int[][] dp = new int[aLen][bLen];
int max = 0;
String temp = "";
for(int i=0; i<aLen; i++){
for(int j=0; j<bLen; j++){
if(aStr[i] == bStr[j]){
if(i != 0 && j != 0){
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = 1;
}
}
if(dp[i][j] > max){
max = dp[i][j];
temp = b.substring(j+1-max, j+1);
}
}
}
System.out.println(temp);
}
}
写出一个程序,接受一个由字母、数字和空格组成的字符串,和一个字符,然后输出输入字符串中该字符的出现次数。(不区分大小写字母)
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
String str = in.nextLine();
String temp = in.nextLine();
Character target = temp.charAt(0);
int res = 0;
for(int i=0; i<str.length(); i++){
if(Character.toUpperCase(target) == Character.toUpperCase(str.charAt(i))){
res++;
}
}
System.out.println(res);
}
}
注意: 用 nextLine 接收输入,因为可能空格,以后接收一行我们都用 nextLine
统计字符串中含多少字符 (0 ~ 127 范围)
public class CharacterStatistic {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
Set<Character> set = new HashSet();
char[] strArr = str.toCharArray();
for (int i=0; i<strArr.length; i++){
if(strArr[i]>=0 && strArr[i]<=127) {
set.add(strArr[i]);
}
}
System.out.println(set.size());
}
}
输出一个数的所有质数因子。
对本题, 我们要明确一点: 所有的合数都能由比其更小的质数的乘积表示 。即:当我们除 4 时, 早就被 2 这个质数过滤掉了 。
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
long a = in.nextLong();
for(int i=2; i<=Math.pow(a, 0.5); i++){
while(a % i == 0){
System.out.print(i + " ");
a /= i;
}
}
if(a != 1){
System.out.println(a);
}
}
}
有N条线段,长度分别为a[1]-a[N]。现要求你计算这N条线段最多可以组合成几个直角三角形,每条线段只能使用一次,每个三角形包含三条线段。
输入:
1
7 3 4 5 6 5 12 13
输出:
2
说明: 可以组成2个直角三角形(3,4,5)、(5,12,13)
翻译:就是求满足题意的组合数量
import java.util.function.ToIntFunction;
/**
* @author wanqingLiu
* @date 2023/3/20 13:47
*/
public class RightTriangleNum {
public static final int SIDE_NUMBER = 3;
static int res = 0;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 得到数据组数 n
int N = Integer.parseInt(scanner.nextLine());
while (N != 0) {
String cur = scanner.nextLine();
String[] strs = cur.split("\\ ");
int[] nums = Arrays.stream(strs).mapToInt(value -> Integer.parseInt(value)).toArray();
int n = nums[0];
int[] numsTemp = new int[n];
for (int i = 0; i < n; i++) {
numsTemp[i] = nums[i + 1];
}
Arrays.sort(numsTemp);
boolean[] idxs = new boolean[n];
// 对 nums 回溯求满足题意的组合数(就是满足勾股定理的组合)
backTrace(new ArrayList<>(), numsTemp, n, 0, idxs);
System.out.println(res);
res = 0;
N--;
}
}
// 如何避免重复 —— 记录 index 的数组, 然后将用过的 index 设置为下次不容许使用
public static void backTrace(List<Integer> list, int[] nums, int n, int startIndex, boolean[] idxs) {
if (list.size() > SIDE_NUMBER) { // 剪枝操作
return;
}
// 用过的不能再用 , 标记用过
if (list.size() == SIDE_NUMBER && isRightTriangle(list, nums)
&& !idxs[list.get(0)] && !idxs[list.get(1)] && !idxs[list.get(2)]) {
idxs[list.get(0)] = true;
idxs[list.get(1)] = true;
idxs[list.get(2)] = true;
res++;
return;
}
for (int i = startIndex; i < n; i++) {
if (!idxs[i]) { // 每个边只能用一次
list.add(i);
backTrace(list, nums, n, i + 1, idxs);
list.remove(list.size() - 1);
}
}
}
/*
勾股定理判断是否可组成直角三角形
*/
public static boolean isRightTriangle(List<Integer> list, int[] nums) {
Collections.sort(list);
int a = nums[list.get(0)];
int b = nums[list.get(1)];
int c = nums[list.get(2)];
return (a * a + b * b) == c * c;
}
}
ps: 调代码调到吐血 , QWQ ~~~
import java.util.*;
// 思路:map 记录每个单词出现的次数,按出现次数从大到小,赋予漂亮度
// 涉及到 map 排序问题
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int N = Integer.parseInt(in.nextLine());
while (N != 0) { // 注意 while 处理多个 case
String cur = in.nextLine();
Integer[] charNum = new Integer[26];
Arrays.fill(charNum, 0);
for(int i=0; i(o2-o1));
int ans = 0;
int temp = 26;
for(int i=0; i<26; i++){
if(charNum[i] == 0){
break;
}
ans += charNum[i] * temp;
temp--;
}
System.out.println(ans);
N--;
}
}
}