【JAVA】每日练习——02

  • Post author:
  • Post category:java



目录


一、选择题基础概念


二、[编程题]计算糖果


三、[编程题]进制转换


四、[编程题]统计回文


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 的区别:



  1. String 不可变对象:


    String 类型改变时,

    会生成新的 String 对象,指针指向新 String 对象

    ;生成对象会对系统性能产生影响,JVM 的 GC 开始工作,性能会降低。


  2. StringBuffer 类:


    对 StringBuffer 对象本身进行操作,不生成新对象。


    字符串对象经常改变的情况下,推荐使用 StringBuffer ,



    StringBuffer 主要用在全局变量中



  3. 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;
    }
}



版权声明:本文为qq_45864756原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。