蓝桥杯(java):特殊回文数,十进制转十六进制,十六进制转十进制,十六进制转八进制,数列排序

人生不易,生活无趣。一起来找点乐子吧。

 

 

特殊回文数:

问题描述
  123321是一个非常特殊的数,它从左边读和从右边读是一样的。
  输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n 。
输入格式
  输入一行,包含一个正整数n。
输出格式
  按从小到大的顺序输出满足条件的整数,每个整数占一行。
样例输入
52
样例输出
899998
989989
998899
数据规模和约定
  1<=n<=54。

相比较上题的回文数,多了一个“各位数字之和为n”的条件,也就是多了一层判断。还是我们上次提到的那个问题,怎样把数字的各个位取出来。

上次提了一下,将数字当成字符串,一个个取出来,转换成数值类型计算,这样就不需要去考虑数学运算来一个个取出各位数了。

首先判断回文数,用我们上次的那个方法,依旧当成字符串,倒置后判断是否与原串相等。内层判断则判断各位数字和是否为n,这里说一个新的方法,String.toCharArray(),看方法名字也知道是干什么的了吧。返回的是char数组,如果学过python其实就是返回list(string)。我们要做的就是遍历这个数组,每个数取出来转成数值类型求和就可以了。

示例代码:

import java.util.*;

public class Main {
	public static void main(String args[]){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		sc.close();
		String s;
		for(int i = 10000;i<1000000;i++){
			s = ""+i;
			if(new StringBuilder(s).reverse().toString().equals(s)){
				int sum = 0;
				char c[] = s.toCharArray();
				for (int j = 0;j<c.length;j++){
					sum += Integer.parseInt(String.valueOf(c[j]));
				}
				if(sum == n){
				System.out.println(i);
				}
			}
		}
	
	}
}

 

 

十进制转十六进制:

问题描述
  十六进制数是在程序设计时经常要使用到的一种整数的表示方式。它有0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共16个符号,分别表示十进制数的0至15。十六进制的计数方法是满16进1,所以十进制数16在十六进制中是10,而十进制的17在十六进制中是11,以此类推,十进制的30在十六进制中是1E。
  给出一个非负整数,将它表示成十六进制的形式。
输入格式
  输入包含一个非负整数a,表示要转换的数。0<=a<=2147483647
输出格式
  输出这个整数的16进制表示
样例输入
30
样例输出
1E

这个东西其实超简单,不用去自己编写逻辑处理,Integer.toHexString(int)方法直接使用,将int参数转为十六进制字符串,有一点需要注意,字母的大小写。

比如样例输入30,方法输出是1e,所以注意将最后字符串结果字母变成大写即可。(这个也有方法啊亲。)

import java.util.*;

public class Main{
public static void main(String args[]){
	Scanner sc = new Scanner(System.in);
	int a = sc.nextInt();
	sc.close();
	System.out.println(Integer.toHexString(a).toUpperCase());
}
}

 

 

十六进制转十进制:

问题描述
  从键盘输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出。
  注:十六进制数中的10~15分别用大写的英文字母A、B、C、D、E、F表示。
样例输入
FFFF
样例输出
65535

这个东西……有方法,不用急,先介绍下它,Integer.parseInt(string, int)。参数string是需要表示的字符串,后面的int是表示基数。十进制的基数是十,十六进制基数是十六。仅此而已,程序结束了:

import java.util.*;

public class Main{
public static void main(String args[]){
	Scanner sc = new Scanner(System.in);
	String s = sc.nextLine();
	sc.close();
	System.out.println(Integer.parseInt(s, 16));
}
}

执行完75分,恭喜你啊兄dei,什么原因!!!嗯……最开始的问题,数据规模超出了,你看一下结果,最后一个数据测试不正确,so那个Integer.parseInt(s,16)换成Long.parseLong(s,16),执行完,100分,perfect。

有点坑爹啊,所以良心建议,能用Long的时候不用Integer,ok?不然跟玩游戏一样怎么没的都不知道。

《蓝桥杯(java):特殊回文数,十进制转十六进制,十六进制转十进制,十六进制转八进制,数列排序》

 

所以你现在回头看它想要训练你的关键字:

《蓝桥杯(java):特殊回文数,十进制转十六进制,十六进制转十进制,十六进制转八进制,数列排序》

一个都没用到~~~

 

 

别急兄嘚,下面这个就有点烦了:

十六进制转八进制:

问题描述
  给定n个十六进制正整数,输出它们对应的八进制数。

输入格式
  输入的第一行为一个正整数n (1<=n<=10)。
  接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。

输出格式
  输出n行,每行为输入对应的八进制正整数。

  【注意】
  输入的十六进制数不会有前导0,比如012A。
  输出的八进制数也不能有前导0。

样例输入
  2
  39
  123ABC

样例输出
  71
  4435274

  【提示】
  先将十六进制数转换成某进制数,再由某进制数转换成八进制。

我要说的东西很多,不想看的直接滑到最下面看代码吧。

好像思维逻辑上并没有什么难度,前面两题我们做了十进制转其他进制,其他进制转十进制,那我们就以十进制做桥梁,转两次就可以达到目的。搞他:

import java.util.*;

public class Main{
public static void main(String args[]){
	
	Scanner sc = new Scanner(System.in);
	int n = sc.nextInt();
	String arr[] = new String[n];
	for(int i = 0;i<n;i++){
		arr[i] = sc.next();
	}
	sc.close();
	for(int i = 0;i<n;i++){
		System.out.println(Long.toOctalString( Long.parseLong(arr[i],16) ) );
	}
}
}

Nice,兄弟,优雅的一批:《蓝桥杯(java):特殊回文数,十进制转十六进制,十六进制转十进制,十六进制转八进制,数列排序》

但是错了,为啥?看题的数据范围

《蓝桥杯(java):特殊回文数,十进制转十六进制,十六进制转十进制,十六进制转八进制,数列排序》

长度不超过10万!!!转换成十进制根本存不下来,必定有溢出损失。我们看转进制的方法.toXXXString(),也就是说除了十进制之外的其他进制都是String类型,而十进制的存储是数值类型,我们拿十进制作为中间桥梁,十六进制太大的时候,数值就会溢出损失,再去转换八进制时,结果就是错的。

在这里我们插入一个问题,String能存储多大的数据?我查了一下,说法不一,有的说没有限制,和计算机的内存有关。有的说1到2G。无论怎样,字符的存储我们不管了(因为够大)。

我们换种思路,既然不能一下全部把十六进制转换成十进制,那我们一点点的转

import java.util.*;

public class Main{
public static void main(String args[]){
	
	Scanner sc = new Scanner(System.in);
	int n = sc.nextInt();
	String arr[] = new String[n];
	for(int i = 0;i<n;i++){
		arr[i] = sc.next();
	}
	sc.close();
	for(int i = 0; i<arr.length;i++){
		String s = change(arr[i]);
		s = s.replaceFirst("^0+", "");
		System.out.println(s);
	}
	
}

public static String change(String s){
	char[] arr = s.toCharArray();
	String temp = "";
	String last = "";
	for(int i = 0;i<arr.length;i++){
		temp += arr[i];
		temp = Integer.toBinaryString(Integer.parseInt(temp, 16));
		if(temp.length() ==1)
			temp = "000"+temp;
		else if(temp.length() == 2)
			temp = "00"+temp;
		else if(temp.length() == 3)
			temp = "0"+temp;
		last += temp;
		temp = "";
	}
	int zero = last.length()%3;
	int n = last.length()/3;
	if (zero == 1){
		last = "00"+last;
		n += 1;
	}else if(zero == 2){
		last = "0"+last;
		n += 1;
	}
	String bajinzhi = "";
	for(int i = 0;i<n;i++){
		temp =last.substring(i*3, i*3+3);
		bajinzhi += Integer.toOctalString(Integer.parseInt(temp,2));
	}
	return bajinzhi;
}
}

我们写一个change方法用于将十六进制转成八进制,先是将十六进制串每个字符转成二进制,再将二进制串转为八进制。这里为什么我们不以十进制做桥梁了呢?将每个十六进制字符转成十进制串,再将十进制串转成八进制串?这是因为我们需要一个对应关系,在我们的学习中,我们知道十六进制,将每个字符按四位二进制展开链接起来,就是十六进制到二进制的转换,而二进制到八进制,即将三位二进制看成一组,转为一位八进制数。这个是众所周知的,但是如果我们以十进制当做桥梁,不存在这个关系,中间还有进位的情况,又会导致结果错误。

上面的方法大家想看就看,不想看就别看了,我说下思路,就是将十六进制转成二进制,再将二进制转成八进制。过程中16-2的转换是四位一组,2-8的是三位一组,中间要补上位数不足的零。在将十六进制转换为二进制完成后,记得算一下长度是不是3的倍数,如果不是记得补齐,不然三位一个转八进制时就会因为位数不足出错。最后输出的时候,记得将八进制前面的0去掉,现在这里说一下去零的方法

s.replaceFirst(“^0+”, “”);是个正则表达式:

将第一个参数的内容替换成后面的内容。简单说一下,^匹配开头,+是指将+之前的单字符扩充1或多次,“^0+”也就是匹配开头的多个零,用“”替换,也就达到了去零的目的。

为什么说不想看就别看了呢。因为:

《蓝桥杯(java):特殊回文数,十进制转十六进制,十六进制转十进制,十六进制转八进制,数列排序》

超时!因为人懒,里面的转换都是调的方法,没得办法,我只能去手动写转进制的方法:

import java.util.*;

public class Main{
public static void main(String args[]){
	
	Scanner sc = new Scanner(System.in);
	int n = sc.nextInt();
	String arr[] = new String[n];
	for(int i = 0;i<n;i++){
		arr[i] = sc.next();
	}
	sc.close();
	for(int i = 0; i<arr.length;i++){
		String s = change(arr[i]);
		s = s.replaceFirst("^0+", "");
		System.out.println(s);
	}
	
}

public static String change(String s){
	String last = "";
	for(int i=0;i<s.length();i++){
		switch(s.charAt(i)){
		case '0': last += "0000";break;
		case '1': last += "0001";break;
		case '2': last += "0010";break;
		case '3': last += "0011";break;
		case '4': last += "0100";break;
		case '5': last += "0101";break;
		case '6': last += "0110";break;
		case '7': last += "0111";break;
		case '8': last += "1000";break;
		case '9': last += "1001";break;
		case 'A': last += "1010";break;
		case 'B': last += "1011";break;
		case 'C': last += "1100";break;
		case 'D': last += "1101";break;
		case 'E': last += "1110";break;
		case 'F': last += "1111";break;
		}
	}
	if (last.length()/3 == 1)
		last = "00"+last;
	else if(last.length()/3 == 2)
		last = "0"+last;
	
	
	String bajinzhi = "";
	String temp = "";
	for(int i=0;i<last.length()/3;i++){
		temp = last.substring(i*3, i*3+3);
		switch(temp){
		case "000": bajinzhi += "0";break;
		case "001": bajinzhi += "1";break;
		case "010": bajinzhi += "2";break;
		case "011": bajinzhi += "3";break;
		case "100": bajinzhi += "4";break;
		case "101": bajinzhi += "5";break;
		case "110": bajinzhi += "6";break;
		case "111": bajinzhi += "7";break;
		}
	}
	return bajinzhi;
}
}

肯定要枚举了,本来想着用一堆if来做判定,看到人家写的文章想起了switch方法。这篇文章在这:

https://blog.csdn.net/kevinbetterq/article/details/62886848

思维很简单吧,但是:

《蓝桥杯(java):特殊回文数,十进制转十六进制,十六进制转十进制,十六进制转八进制,数列排序》

不能原谅!我都手写了,你还要我怎样要怎样,连判断我都用switch写的落落大方。

我想到了这里。

《蓝桥杯(java):特殊回文数,十进制转十六进制,十六进制转十进制,十六进制转八进制,数列排序》

这里顺便简单谈一下语言对变量的存储吧。对于c和java这种,我们声明一个变量,就会留下一块地方来存储变量的值。

例如以上面为例,声明了last,我们就有了一块空间存数据,但是对于last的重新赋值,其实是对last那块空间内容的重写,每次赋值都是重写。

返回去我们说下python,你们知道python为什么声明变量的时候不用定义类型吗,那是因为python对于数据的存储机制和java,c等不同。比如python中n = 1这一语句,python是这样做的:

遇到了n,在内存里存储了个n,有了个1,在内存里存了个1,赋值n = 1,ok将n指向1(理解成指针也没什么关系)。后面我们又写了一条语句,n = ‘halo’。同样的:

在内存里存下字符串‘halo’,赋值n,就将n指向‘halo’,原来n指的那个1,后面就会被python的内部机制清理掉。这就是python的处理机制。不用重写,变量不用指明类型。

所以考虑到这里我在想是不是每次重写的时间长了?上面提到的那篇文章中用到了StringBuffer的apped方法,StringBuffer我们前面用到过,对字符串的倒置.reserve()方法。这里对字符串的添加或许快点,我去查了append方法内部实现:

https://blog.csdn.net/guidiannan/article/details/80267435

《蓝桥杯(java):特殊回文数,十进制转十六进制,十六进制转十进制,十六进制转八进制,数列排序》

不太清楚他比我快的原因,但是……不服不行:

《蓝桥杯(java):特殊回文数,十进制转十六进制,十六进制转十进制,十六进制转八进制,数列排序》

看最后代码吧:

import java.util.*;

public class Main{
public static void main(String args[]){
	
	Scanner sc = new Scanner(System.in);
	int n = sc.nextInt();
	String arr[] = new String[n];
	for(int i = 0;i<n;i++){
		arr[i] = sc.next();
	}
	sc.close();
	for(int i = 0; i<arr.length;i++){
		String s = change(arr[i]);
		System.out.println(s.replaceFirst("^0+", ""));
	}
	
}

public static String change(String s){
	StringBuffer s1=new StringBuffer("");
	for(int i=0;i<s.length();i++) {
		switch(s.charAt(i)) {
		case '0':s1.append("0000");break;
		case '1':s1.append("0001");break;
		case '2':s1.append("0010");break;
		case '3':s1.append("0011");break;
		case '4':s1.append("0100");break;
		case '5':s1.append("0101");break;
		case '6':s1.append("0110");break;
		case '7':s1.append("0111");break;
		case '8':s1.append("1000");break;
		case '9':s1.append("1001");break;
		case 'A':s1.append("1010");break;
		case 'B':s1.append("1011");break;
		case 'C':s1.append("1100");break;
		case 'D':s1.append("1101");break;
		case 'E':s1.append("1110");break;
		case 'F':s1.append("1111");break;
		}
		
	}
	s = s1.toString();

	if (s.length()%3 == 1)
		s = "00"+s;
	else if(s.length()%3 == 2)
		s = "0"+s;
	
	
	StringBuffer s2=new StringBuffer("");
	for(int i=0;i<s.length();i+=3) {
		String s3=s.substring(i, i+3);
		switch (s3) {
		case "000":s2.append('0');break;
		case "001":s2.append('1');break;
		case "010":s2.append('2');break;
		case "011":s2.append('3');break;
		case "100":s2.append('4');break;
		case "101":s2.append('5');break;
		case "110":s2.append('6');break;
		case "111":s2.append('7');break;
		}
	}

	return s2.toString();
}
}

得,到这算是全部问题都解决了,我还是觉得这种方法好蠢,有优雅的方法,希望不惜吝教,评论写下面喽!

 

 

最后一个:

序列排序:

问题描述
  给定一个长度为n的数列,将这个数列按从小到大的顺序排列。1<=n<=200
输入格式
  第一行为一个整数n。
  第二行包含n个整数,为待排序的数,每个整数的绝对值小于10000。
输出格式
  输出一行,按从小到大的顺序输出排序后的数列。
样例输入
5
8 3 6 4 9
样例输出
3 4 6 8 9

这种应该属于集合操作了吧,我们不要将我们的思维固定在数组上,这里有篇不错的文章:

https://blog.csdn.net/carson_ho/article/details/85043628(值得收藏!)

排序,这里我们尝试着用一个Arrays。Arrays.sort()方法可以对一个数组进行排序,注意这里是原地排序,什么意思。就是对那个数组在数组的存储空间上直接进行排序,那非原地呢?其实就是新生成一个排完序的数组,而对于原数组不进行变动。

示例代码:

import java.util.*;

public class Main{
public static void main(String args[]){
	
	Scanner sc = new Scanner(System.in);
	int n = sc.nextInt();
	int arr[] = new int[n];
	for(int i = 0;i<n;i++){
		arr[i] = sc.nextInt();
	}
	sc.close();
	Arrays.sort(arr);
	for(int i = 0; i<n;i++){
		System.out.printf(arr[i]+" ");
	}
	
}

}

简单到想哭了是不。

排序的方法有很多,选择,插入,快排等等:

https://blog.csdn.net/huosanghuakai1995/article/details/75090370

也许你们有些人觉得这些程序不应该这样写,应该自己去实现,而不是去用写好的方法。嗯……怎么说呢,我觉得要在于你怎么看这个问题,算了,留给你们去评论好了。

 

就先写到这吧。这次的五道题算是完了,哦对了,要说一句,我不是VIP,后面的题都被封着。所以,后面我们就不说“基础练习”了,进入下一块“算法训练”。

 

 

java笔记:

1、字符串转字符数组:String.toCharArray()

2、十进制转其他进制串:Integer.toXXXXString(int)

3、其他进制串转十进制:Integer.parseInt(s,16)或Long.parseLong(s,16),参数说明s为进制串,第二个参数int类型,为进制的基数。

4、字符串转大写:String.toUpperCase()

5、s.replaceFirst(“^0+”, “”),运用正则表达式替换开头0

6、字符串链接,除了string + “123”之外,StringBuffer.append(string),也是个不错的方法,事实证明,比前面那个快。

7、排序,Arrays.sort(array)可对数组array进行原地排序

    原文作者:进制转换
    原文地址: https://blog.csdn.net/qq_41500251/article/details/85058159
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞