目录
Java中 String、StringBuffer 、 StringBuilder 的区别:
一、选择题基础概念
1.队列:先到先服务的作业调度(先进先出)
2.接口interface的合法定义,不能有私有的private,
接口只能由public修饰符修饰
public interface classDemo2 {
public static void main(String[] args) {
}
boolean setFlag(Boolean[] test);
public float get(int x);
public int getSum1(); //不报错
private int getSum(); // 会报错,--->方法不能是私有的 ,私有方法是不可以重写的
}
3.
Java中一个子类只能继承一个父类,但可以实现多个接口 , 实例化子类时会递归调用父类中的构造方法
4.类所实现的接口以及修饰不可以是:final/void
5.程序是算法,但算法不一定是程序;
结构化程序的三种基本结构:顺序、选择、循环
final类是不能被继承的,因此其类里的方法不能是abstract
6.
局部变量使用一定要初始化
7. finally一定会被执行,最后输出false;
finally一般用作资源的关闭
二、[编程题]计算糖果
链接:
计算糖果__牛客网
A,B,C三人,每人手里都有一些糖果,我们不知道他们每个人手上具体有多少个糖果,但是我们知道以下的信息:A – B, B – C, A + B, B + C. 这四个数值.每个字母代表每个人所拥有的糖果数.
现在需要
通过这四个数值计算出每个人手里有多少个糖果
,即A,B,C。这里保证最多只有一组整数A,B,C满足所有题设条件。
输入描述:
输入为一行,一共4个整数,分别为A – B,B – C,A + B,B + C,用空格隔开。 范围均在-30到30之间(闭区间)。
输出描述:
输出为一行,如果存在满足的整数A,B,C则按顺序输出A,B,C,用空格隔开,行末无空格。 如果不存在这样的整数A,B,C,则输出No
示例:
1 -2 3 4—–>2 1 3
解析:1.根据已有的关系式可得到A/B/C/D之间的关系表达式:
A = (a+c)/2; C=(d-b)/2 ; B=(c-a)/2 ;B=(b+d)/2
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt(); //定义输入的四个整数
int b = scanner.nextInt();
int c = scanner.nextInt();
int d = scanner.nextInt();
int A = (a+c)/2; //得到三个人拥有的糖果数与输入数据的关系
int B1 = (c-a)/2;
int B2 = (b+d)/2;
int C = (d-b)/2;
if(B1 != B2) {
System.out.println("No"); //不相等则说明没找到各自的糖果数量
}else{
System.out.println(A+" "+B1+" "+C); //相等则可以求得ABC的值
}
}
}
三、[编程题]进制转换
链接:
进制转换_牛客网
描述:
给定一个十进制数 M ,以及需要转换的进制数 N 。将十进制数 M 转化为 N 进制数。当 N 大于 10 以后, 应在结果中使用大写字母表示大于 10 的一位,
如: ‘A’ 表示此位为 10 , ‘B’ 表示此位为 11 。若 M 为负数,应在结果中保留负号。
输入:7,2 ——> 返回值 “111”
输入:10,16——> 返回值:”A”
解析:
举例说明十进制:123 = 1*
10
^2+2*
10
^1+3*
10
^0
二进制:0110 = 0*
2
^3 +1*
2
^2+1*
2
^1+0*
2
^0
0.定义一个数组table存放字符串:String table = “0123456789ABCDEF”; 可用于表示不同进制的数
table.charAt(m%n)方法:返回table数组指定索引位置(m%n)的字符,即可表示每位数值向不同进制转化的结果
1.求得输入数据m的每一位数值(如:各十百千位的值的分别是多少),采取取余的方法可以获得各个位的值
(如123—>
-
个位:123%10,123/10=12;
-
十位:12%10=2;12/10=1,
-
百位:1%10=1)
2.将得到字符串进行reverse,(取余是从后往前进行的)。
3.考虑输入的数据若为负数,则需要在处理前将其转化为正数,进行区域操作,最后再拼接上负号‘-’
4.因为String类型拼接过程会产生很多临时变量,因此可使用StringBuilder来避免这种情况,同时要
注意,StringBuilder不可直接转化为String,所以在最后要用str.toString()进行类型转换。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 进制转换
* @param M int整型 给定整数
* @param N int整型 转换到的进制
* @return string字符串
*/
public String solve(int m, int n) {
//Stringr str = ""; //定义一个字符串用于接收字符并拼接(+) 若用string完成拼接会喊声大量临时对象,
StringBuilder str = new StringBuilder(); //用StringBuilder的append完成拼接(.append)·
String table = "0123456789ABCDEF";
boolean flg = false; //定义一个标志位,是否交换
if(m < 0) {
m = -m; //把复数转换为正数
flg = true;
}
while(m != 0) { //M给定整数 此处循环可获得输入数字的每一位如:123--->3 2 1(从后往前)
str.append(table.charAt(m%n)); //若用string完成拼接会产生大量临时对象
m = m/n;
}
//如果是负数,则对获取的数拼接一个符号
if(flg) str.append("-"); //如果是负数,则拼接一个符号
return str.reverse().toString(); //由于str是StringBuilder类型,因此需要转化成string类型
// 若此时使用return str.reverse()会报错,不会编译成功
}
}
四、[编程题]统计回文
链接:
统计回文__牛客网
“回文串”是一个正读和反读都一样的字符串
,比如“level”或者“noon”等等就是回文串。有两个字符串A\B将字符串B插入字符串A使产生的字符串是一个回文串。寻找有多少种插入办法可以使新串是一个回文串。如果字符串B
插入的位置不同就考虑为不一样的办法。
例如:
A = “aba”,B = “b”。这里有4种把B插入A的办法:
* 在A的第一个字母之前: “baba” 不是回文
* 在第一个字母‘a’之后: “abba” 是回文
* 在字母‘b’之后: “abba” 是回文
* 在第二个字母’a’之后 “abab” 不是回文
所以满足条件的答案为2
输入描述:
第一行为字符串A
第二行为字符串B 字符串长度均小于100且只包含小写字母
输出描述:
输出一个数字,表示把字符串B插入字符串A之后构成一个回文串的
方法数
解析:
1.回文判断:ret.toString().equals(str.toString() (原函数str=逆置函数ret)
2.寻找多少种方法,需要将字符B插入到A的不同位置,每插入一个位置判断一次是否回文,(从A的最前位置开始便利插入,直到最末尾)
注意!!!StringBuffer不能直接转变为String类型,使用toString方法:
ret.toString().equals(str.toString())—>判断两个String字符串是否相等
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str1 = scanner.nextLine();
String str2 = scanner.nextLine(); //输入两个字符串
int len = str1.length();
int count = 0;
for(int i=0; i <= len; i++) { //便利A字符串,//创建一个对象str来接受插入的新数组
StringBuffer str = new StringBuffer(str1); //创建初始str存的是A字符串的元素
str.insert(i,str2); //在str字符串的i位置插入str2字符串 --->得到str为插入B之后的新的字符串
StringBuffer tmp = new StringBuffer(str); //tmp存放插入字符串B后的str
StringBuffer ret = tmp.reverse(); //ret是插入字符串之后的逆置字符串
if(ret.toString().equals(str.toString())) {
count++;
}
}
System.out.println(count);
}
}
Java中 String、StringBuffer 、 StringBuilder 的区别:
String 不可变对象:
String 类型改变时,
会生成新的 String 对象,指针指向新 String 对象
;生成对象会对系统性能产生影响,JVM 的 GC 开始工作,性能会降低。
StringBuffer 类:
对 StringBuffer 对象本身进行操作,不生成新对象。
字符串对象经常改变的情况下,推荐使用 StringBuffer ,
StringBuffer 主要用在全局变量中
。
StringBuilder类:
在需要拼接+时使用,是线程不安全的,用完就可丢弃。
五、[编程题]连续最大和
链接:
连续最大和_滴滴笔试题_牛客网
一个数组有 N 个元素,求连续子数组的最大和。 例如:[-1,2,1],和最大的连续子数组为[2,1],其和为 3
输入描述:
输入为两行。
第一行一个整数n(1 <= n <= 100000),表示一共有n个元素
第二行为n个数,即每个元素,每个整数都在32位int范围内。以空格分隔。
输出描述:
所有连续子数组中和最大的值。
输入:
3
-1 2 1—->输出:3
解析:(求子数组的和最大),使用 动态规划DP
1.状态方程式:
max(dp[i]) = getMax(max(dp[i -1]) + arr[i],arr[i])
dp[i] : 以数组
下标为i 的数为结尾
的
最大子序列和 .如数组:[6,-3,-2,7,-15,1,2,2], dp[2]=(6-3-2=1), dp[3]=(6-3-2+7=8)
import java.util.Scanner;
public class Main{
public static int getMax(int a,int b) {
return a > b ? a : b; //满足a>b返回a,不满足则返回b
}
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int size = scanner.nextInt();
int[] array = new int[size]; //定义一个数组存放第二行的数据
for(int i= 0;i < size; i++) {
array[i] = scanner.nextInt(); //第二行输入的数据放入数组中
}
int sum = array[0];
int max = array[0];
for(int i = 0; i < size; i++) {
sum = getMax(sum+array[i],array[i]);
if(sum >= max) {
max = sum;
}
}
System.out.println(max);
}
}
六、[编程题]把字符串转换成整数
链接:
把字符串转换成整数__牛客网
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为 0 或者字符串不是一个合法的数值则返回 0
①字符串中可能出现任意符号,出现除 +/- 以外符号时直接输出 0
②字符串中可能出现 +/- 且仅可能出现在字符串首位。
输入描述:
输入一个字符串,包括数字字母符号,可以为空
输出描述:
如果是合法的数值表达则返回该数字,否则返回0
如:
“+2147483647”—–>2147483647
“1a33”—–>0
解析:
1.上次计算的结果*10,相当于10进制进位,然后加当前位的值。
2.考虑空字符串、正负号处理、数字串中存在非法字符的情况。
import java.util.*;
public class Solution {
public int StrToInt(String str) {
char[] ch = str.toCharArray(); //把字符串转变为字符数组
if(ch == null || ch.length == 0) {
return 0;
}
int flg = 1; //定义一个标志位
if(ch[0] == '-') { //如果第一个字符是‘-’,则标志位是-1,为负数
flg = -1;
ch[0] = '0';
}else if(ch[0] == '+') {//如果第一个字符是‘+’,则标志位代表1
flg = 1;
ch[0] = '0';
}
int sum = 0;
for(int i = 0;i < str.length();i++) {
if(ch[i] < '0' || ch[i] > '9') {
sum = 0; //若不是合法的数字,则返回0
break;
}
sum = sum*10 + ch[i] -'0'; //是合法的数字则输出数字,拼接每一位获得的数字
}
return flg*sum;
}
}
七、[编程题]不要二
链接:
不要二__牛客网
二货小易有一个W*H的网格盒子,网格的行编号为0~H-1,网格的列编号为0~W-1。每个格子至多可以放一块蛋糕,任意两块蛋糕的欧几里得距离不能等于2。欧几里得距离:
( (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) ) 的算术平方根—–>(x1-x2) ^2 + (y1-y2) ^2 !=4即可
小易想知道最多可以放多少块蛋糕在网格盒子里。
输入描述:
每组数组包含网格长宽W,H,用空格分割.(1 ≤ W、H ≤ 1000)
输出描述:
输出一个最多可以放的蛋糕数
解析:两个位置满足:(x1-x2) ^2 + (y1-y2) ^2 =4不可放,根据表达式得出:只有0+4和4+0的情况符合此表达式,也即:
- 1.(x1-x2) ^2 =0, (y1-y2) ^2 = 4 —->x1==x2,y1=y2+2 –>[i][j+2]
- 2.(y1-y2) ^2 =0, (x1-x2) ^2 = 4 —->y1==y2, x1=x2+2 –>[i+2][j]
故位置[i][j+2]和[i+2][j]不能蛋糕,其余情况均可
,同时注意[i+2],[j+2]越界
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int w= scanner.nextInt();
int h= scanner.nextInt();
int count = 0;
int[][] arr = new int[w][h]; //定义一个二维数组,初始化每个维度
for(int i=0;i < w;i++){
for(int j=0;j < h;j++) {
if(arr[i][j] == 0) { //可以放,计数器++
count++;
// 可以放蛋糕的前提下,欧几里得距离不能为2
if(i+2 < w) { // 防止数组越界,
arr[i+2][j] = 1; //不能放蛋糕
}
if(j+2 < h) {
arr[i][j+2] = 1;
}
}
}
}
System.out.println(count);
}
}
八、[编程题]两种排序方法
链接:
两种排序方法__牛客网
考拉有n个字符串,任意两个字符串长度都是不同的。考拉最近学习到有
两种字符串的排序方法
: 1.根据字符串的
字典序排序
。例如:car” < “carriage” < “cats” < “doggies < “koala”
2.根据字符串的
长度排序
。例如:”car” < “cats” < “koala” < “doggies” < “carriage”
考拉的这些字符串排列顺序是否满足这两种排序方法,请验证:
输入描述:
输入第一行为字符串个数n(n ≤ 100)
接下来的n行,每行一个字符串,字符串长度均小于100,均由小写字母组成
输出描述:
如果字符串是根据字典序排列输出”lexicographically”;
如果根据长度排列 输出”lengths”, 如果两种方式都符合输出”both”,否则输出”none”
import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
String[] str = new String[n]; //读入字符串 (后面每行存在一个字符串数组中,
for(int i = 0;i<n;i++) {
str[i] = scanner.nextLine(); //数组中每个元素是一个字符串)
}
if(isSortedByDict(str) && isSortedByLength(str)) {
System.out.println("both");
}else if(isSortedByDict(str)) {
System.out.println("lexicographically");
}else if(isSortedByLength(str)) {
System.out.println("lengths");
}else {
System.out.println("none");
}
}
public static boolean isSortedByDict(String[] str) { //判断数组是否是按照字典排序
for(int i=0;i < str.length -1;i++) { // str.length-1防止比较到i+1时数组越界
//compareTO:str[i]+str[i-1] > 0说明钱一个数组元素(字符串)字典序更大
if(str[i].compareTo(str[i+1]) > 0) {
return false;
}
}
return true;//反之,后一个元素,字典序更大,返回true
}
public static boolean isSortedByLength(String[] str) { //判断是否是按照长度排序
for(int i=0;i < str.length-1;i++) {
if(str[i].length() > str[i+1].length()) { //当前数组长度更大,说明不是按照长度及逆行的升序排序
return false;
}
}
return true;
}
}
方法二:集合类容器比较是否相等时,比较的是内部的值,而不是这两个容器的句柄(引用):
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception{
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine());
List<String> arr = new ArrayList<>(); //创建一个集合类接受多行输入 数组列表
for(int i = 0; i < n; ++i) arr.add(sc.nextLine()); //每输入一行作为一个元素放入列表arr
List<String> newarr = new ArrayList<>(arr); //创建一个新字符串列表newarr,对其进行排序
Collections.sort(newarr);
//按照字典排序
boolean bydict = newarr.equals(arr); // 比较集合类容器arr/newarr是否相等,相等则说明是按照字典排序
//按照长度排序
boolean bylength = true; //创建一个对象bylength ,代表按照长度排序
for(int i = 0; i < arr.size()- 1; ++i){ //arr.size()- 1避免数组越界
if(arr.get(i).length() > arr.get(i + 1).length()){
bylength = false;
break;
}
}
if(bydict && bylength){
System.out.println("both");
return;
}
if(bydict ){
System.out.println("lexicographically");
return;
}
if(bylength){
System.out.println("lengths");
return;
}
System.out.println("none");
}
}
九、[编程题]最大公约数
链接:
最大公约数__牛客网
求出两个数的最大公约数,如果有一个自然数a能被自然数b整除,则称a为b的倍数,b为a的约数。几个自然数公有的约数,叫做这几个自然数的公约数。公约数中最大的一个公约数,称为这几个自然数的最大公约数。
输入描述:
输入两个整数n,m, n和m的范围是[1,10^9][1,10^9]
输出描述:
求出n、m的最大公约数。
解析:(A,B):指两数之间的最大公约数–>欧几里得算法(辗转相除法):
(
A,B)
= (small,big % small)
=(A*K+B,B)=(B*K+A,A)
如:(24,18)=(18,24%18)=(18,6)=(6,18%6)=(6,0)—>最大公约数6
(10,4)=(4,10%4)=(4,2)=(2,4%2)=(2,0)—>最大公约数2
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long m = sc.nextInt();
long n = sc.nextInt();
long ret = gcd(m,n);
System.out.println(ret);
}
public static long gcd(long m,long n) { //求最大公约数
if(m==n) return m;
if(m < n) {
long tmp = m;
m = n;
n = tmp;
}
long ret; //ret接受m&n的余数
while((ret=m%n) >0) {
m = n;
n = ret;
}
return n;
}
public static long gcd1(long m,long n) { //求最大公约数
if (m == n)return m;
long big = m > n ? m : n;
long small = m < n ? m : n;
if (big % small == 0) return small;
return gcd1(small,big%small);
}
}
十、[编程题]最小公倍数
链接:
最小公倍数__牛客网
求两个数的最小公倍数,两个数的最小公倍数为:能被这两个数同时整除的最小的数。
输入描述:
输入两个整数n,m。1≤n,m≤1.5×1051\leq n,m\leq 1.5\times10^51≤n,m≤1.5×105。 答案确保在int范围以内。
输出描述:
输出两个数的最小公倍数。
解析:最小公倍数:A*B/(A,B)的最大公约数
欧几里得算法(辗转相除法):(A,B)=(A*K+B,B)=(B*K+A,A)
注意!!! 考虑给出的范围,若int不能包含要求的范围,则使用long型
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long m = sc.nextInt();
long n = sc.nextInt();
long flg = gcd(m,n);//flg接受最大公约数
long a = m*n/flg; //接受最小公倍数
System.out.println(a);
}
public static long gcd(long m,long n) { //求最大公约数
if(m==n) return m;
if(m < n) {
long tmp = m;
m = n;
n = tmp;
}
long ret; //ret接受m&n的余数
while((ret=m%n) >0) {
m = n;
n = ret;
}
return n;
}
}