算法刷题0-java知识补充

本文分享了算法准备过程中Java编程的刷题技巧,涉及IO流的Scanner、BufferedReader和StreamTokenizer的使用,以及快速输入输出处理。此外,文章还介绍了Stack数据结构的基本概念和String相关操作,如字符和字符串互换、大小写转换等。
摘要由CSDN通过智能技术生成

算法刷题说明

本博客会记录准备秋招过程中的算法刷题过程,包括自己总结的思路和分析步骤,以这种教别人的方式去总结分析,也是我一直推崇的 费曼学习法 的一种形式。(菜鸡只能用这种方式去不断学习了,如果文中有不对的地方,还请各位大佬多担待,指出问题,我会虚心接受并改正的)

所有的题都是根据 算法随想录 一步步做下去,算法随想录也有b站的视频,全部都是开源的,讲的深入浅出,强烈安利。

我主要使用java进行刷题,所以也会补充一些在刷算法的时候的java的相关知识点,这篇博文主要是记录java的相关知识点,后续的每一个算法内容都会专门生成一个章节,每一个知识点一个章节的发布。

0 刷题的时候需要知道的一些操作

0.0 待做事项

  1. 使用map实现卡码网的11题
  2. 使用BufferedReader实现15和16题。

0.1 关于输入输出

0.1.0 补充说明

  1. IO流

    • 在Java的输入中,是以输入流的形式进入程序,因此无法直接指定输入的类型,仅能读取键盘上的内容,返回一个ASCII码,所以在使用输入流的时候,本质是一串ASCII码,需要将类型强转至char,才能正确显示。
    • 在Java的IO流中,键盘所输入的会先存放到缓冲流中,当按下Enter键的时候,将缓重流中的数据写入到内存中,因为此性质,我们无法在键盘输入的过程中直接获取内容。
  2. 快读和快输出

    • Java算法必备(背)之快读快输出
    • 为什么要快读和快输出
    • 可是当数据比较大的时候(个人经验,洛谷数据过万,PTA数据过两千,建议使用快读),我们快读主要是使用io包的StreamTokenizer类。当数据的数量级为10^5时,用StreamTokenizer类差不多好像是要比Scanner快个300ms左右。

0.1.1 输入的几种形式

  1. Scanner对象输入(需要导入java.util.Scanner)

    import Java.util.Scanner;
    //定义scanner对象,需要传入参数System.in,这是系统标准输入流
    Scanner sc = new Scanner(System.in);
    
    //读取一整行的数据转换成String,遇到换行符停止,且换行符也会被读入,光标放在下一行
    String line = sc.nextLine();
    
    //读取一个int数据,光标放在该数据后面
    int num = sc.nextInt();
    
    //读取一个浮点数据,光标放在该数据后面
    int num1 = sc.nextFloat();
    int num2 = sc.nextDouble();
    
    //读取一个字符串数据,遇到空格或者换行符停止,光标停止在数据后,同一行。
    String str = sc.next();
    
    
  2. BufferedReader(要导入java.io.BufferedReader)

    • 该方法采用的是缓存输入流的形式,
    • BufferedReader和正常的io流成员类型基本一致,唯一不同是类的构建,BufferedReader需要使用字符输入流作为基类。
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class BufferedReaderTest {
        public static void main(String[] args) throws IOException {
            //缓冲输入
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            //while((line = br.readLine)!=-1)
            String[] line = br.readLine().split(" ");
            int n = Integer.parseInt(line[0]), m = Integer.parseInt(line[1]);
            int[][] nums = new int[n][m];     
            for ( int i = 0; i < n; i++ ) {
                line = br.readLine().split(" ");    
            for ( int j = 0; j < m; j++ ) {             
                nums[i][j] = Integer.parseInt(line[j]);
            }
        }
        }  
    }
    
    
  3. Stream Tokenizer类(对应输出是PrintWriter类)(快读与快输出)

    • 【Java基础】StreamTokenizer使用详解
    • StreamTokenizer类接收输入流并将其解析为“令牌”,允许一次读取一个令牌。 解析过程由表和多个可以设置为各种状态的标志来控制。 流标记器可以识别标识符,数字,引用的字符串和各种注释样式。
    • 从输入流读取的每个字节被视为’\u0000’至’\u00FF’范围内的’\u0000’ ‘\u00FF’ 。 字符值用于查找字符的五个可能属性: 空格 , 字母 , 数字 , 字符串引号和注释字符 。 每个角色都可以有零个或多个这些属性。
    • 注意:使用StreamTokenizer类要记得抛出I/O异常。
    import java.io.*;
    
    //普通用法
    StreamTokenizer st =new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); 
    st.nextToken(); // 获取下一组标记   默认是按照空格分割的   回车,tab是结束符 
    int i=(int) st.nval;     //st.navl默认解析出的格式是double
     
    st.nextToken();     
    double j=st.nval; 
     
    st.nextToken();     
    String s=st.sval;       //st.savl默认解析出的格式是String
    
    //多组输入
    public class Main {
        public static void main(String[] args) throws IOException {
    
            StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
            //PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
            int a, b;
            while(in.nextToken() != StreamTokenizer.TT_EOF)  // 表示读到了文件末尾
            {
                a = (int)in.nval;
                in.nextToken();
                b = (int)in.nval;
                //out.println(a + b);
                System.out.println("a + b = "+(a+b));
            }
            //out.flush();
        }
    }
    
    
    • 补充说明:(三个常用方法/函数)
      • quoteChar(int ch) - 指定当前字符为当前tokenizer中的分隔符,在两个符号之间被当作一个字符串解析。(多个ch在一起时,只认为第一个是分隔符)
      • whitespaceChars(int low, int hi) - 字符low与hi之间的所有字符都被当作为空格符,即被认识为tokenzier的分隔符。(多个ch在一起时,被认为是同一个分隔符)
      • wordChars(int low, int hi) - 字符low与hi之间的所有字符都被当作为单词的要素。 一个单词是由一个单词要素后面跟着0个或者更多个单词要素或者数字要素。
    • 使用的补充说明:
      • 如果想要’a’作为分隔符,推荐st.whitespaceChars(‘a’,‘a’);不推荐st.quoterChar(‘a’),因为在多个a时,后者不会把它当成一个分隔符。比如"1234aaa567",后者会分割成"1234"和"567",中间的’a’全部被当成空格,而前者会分割为"1234.0",“aaa567”,会保留’a’。
      • 数字和字母连接在一起时会被认为是字符串,比如"aaa123",这会被认为是一个整体字符串。分开则不会,比如"aaa 123"。
    • 调用nextToken方法后,该字段包含刚刚读取的令牌类型。 对于单个字符标记,其值为单个字符,转换为整数。 对于带引号的字符串标记,其值为引用字符。 否则,其值为以下之一:
      • TT_WORD表示令牌是单词。
      • TT_NUMBER表示令牌是一个数字。
      • TT_EOL表示已读取行尾。 如果使用参数true调用eolIsSignificant方法,则该字段只能具有此值。
      • TT_EOF表示已到达输入流的末尾。
  4. 标准系统输出System.out
    Java学习-System.out.println,system.out.print,system.out.printf的区别
    System.out.printf()的使用方法

    System.out.println(参数) //会换行,参数可以为空,为空则表示只换行
    System.out.print(参数)  //不会换行,且参数不能为空。
    System.out.printf("格式",参数)//按照格式输出参数,f是format的意思。
    
  5. StringBuilder输出

    //StringBuilder输出
    StringBuilder sb = new StringBuilder();
    for ( int i = 0; i<n; i++) {
        for ( int j = 0; j < m; j++ ) {
            sb.append(nums[i][j]+" ");
        }
        sb.append("\n");
    }
    System.out.println(sb.toString());
    
  6. PrintWriter输出

    • 将对象的格式表示打印到文本输出流。 这个类实现了全部在发现print种方法PrintStream 。 它不包含用于编写原始字节的方法,程序应使用未编码的字节流。
    • 不像PrintStream类,如果启用自动刷新,它只会在调用的println,printf,或format方法来完成,而不是当一个换行符恰好是输出。 这些方法使用平台自己的行分隔符而不是换行符。
    • 这个类中的方法不会抛出I / O异常,尽管它的一些构造函数可能。 客户可以通过调用checkError()查询是否发生错误。
    import java.io.*;
    public class test {
        public static void main(String args[]){
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
            pw.print();//不换行输出
            pw.println();//换行输出
            pw.printf();//格式化输出
            pw.flush();//关闭输出流
        }
    }
    
    • PrintWriter类的使用相对而言比较简单,就是把我们平时的输出的System.out替换成对应的快输出的实例对象名,唯一需要比较注意的就是最后记得flush(),如果不使用flush(),它会一直不输出,只放在输出缓存流里面。

0.2 关于字符和字符串

0.2.1 字符串和字符的互换

  1. String转换为char

    String str = "we are friend";
    
    //方法一,使用charAt()
    int index = 1;
    char ch = str.charAt(index);//会把index为1的字符转换为字符,在这里是e。
    
    //方法二,使用toCharArray(),把整个string转换成字符串数组char[]
    char[] chArray = str.toCharArray();
    char ch = chArray[index];
    
    
  2. char转换成String

    //1.效率最高的方法,使用valueOf()
    String s = String.valueOf('c'); 
    
    //2.将一个char数组转换成String
    String s = String.valueOf(new char[]{'c'}); 
    
    //3.Character.toString(char)方法实际上直接返回String.valueOf(char)
    String s = Character.toString('c');
    
    //4.类似3
    String s = new Character('c').toString();
    
    //5.效率最低
    String s = "" + 'c';
    // 虽然这个方法很简单,但这是效率最低的方法
    // Java中的String Object的值实际上是不可变的,是一个final的变量。
    // 所以我们每次对String做出任何改变,都是初始化了一个全新的String Object并将原来的变量指向了这个新String。
    // 而Java对使用+运算符处理String相加进行了方法重载。
    // 字符串直接相加连接实际上调用了如下方法:
    // new StringBuilder().append("").append('c').toString();
    
    //6.使用string对象新建
    String s = new String(new char[]{'c'});
    
    

    补充说明:
    * 字符/字符数组转字符串,不能直接toString(),对于字符来说,没有这样的方法,对于字符数组来说,本身是一个数组,toString()方法是输出其地址,除非重写了该方法。

0.2.2 字符串和数字的互换

  1. 数字转字符串
    // 数字转字符串 method1
    	int number = 5;
    	String str = String.valueOf(number);
    	System.out.println(str);
    
    // 数字转字符串 method2
            int number = 5;
            Integer itr = number;  //int装箱为对象,再调用对象的toString方法
            String str = itr.toString(); //或者直接 String str = Integer.toString(number);
            System.out.println(str);
    
    // 数字转字符串 method3
            int number = 5;
            String str = number + "";
            System.out.println(str);
    
    
  2. 字符串转数字
    // 字符串转数字
    	String str = "123";
        //方法一
    	Integer num1 = new Integer(str);	
        //方法二
        int num2 = Integer.parseInt(str);
        //方法三
        Integer num3 = Integer.valueOf(str);
    
    
  3. 数字、字符互相
    // 数字转字符
    	// 不能直接转换,如下图。因此需借助数字转字符串。
    	// 首先将数字转为字符串,再获取字符
    	int number = 5; //注意这里数字只能是个位数并且不能为负
    	String temp = Integer.toString(number);
    	char ch = temp.charAt(0);
    	System.out.println("数字转字符:"+ch);
    
    // 字符转数字
            // 先把字符转为字符串,再转换为数字
            char ch = '5';
            String temp = String.valueOf(ch);
            int a = Integer.parseInt(temp);
            System.out.println(a);
            //或者
            int a = ch - '0';
    
    

0.2.3 字符串操作函数

  1. 大小写转换----String.toLowerCase() 或 String.toUpperCase()

    • toLowerCase()方法将String转换为小写。如果字符串中没有应该被转换的字符,则将原字符串返回,否则返回一个新的字符串。
    • 语法:str.toLowerCase()
    • toUpperCase()方法将Srtring转换为大写。如果字符串中没有应该转换的字符,则将原字符串返回,否则返回一个新的字符串。
    • 语法:str.toUpperCase()
    • 说明:使用toLowerCase()方法和toUpperCase()方法进行大小写转换时,数字或非字符不受影响。
  2. 去除头尾的空格----String.trim()

    • 对一个String修剪头尾的空格,比如:" yes you know ".trim(),则会变成 “yes you know”。
  3. 长度信息

    • 对于数组:array.length,数组是一个初始化就确定好长度的数据类型,所以length是它的一个属性。
    • 对于字符串:String.length(),
    • 对于集合ArrayList来说,是大小: ArrayList.size()
    • 因为String和ArrayList都是对象,所以是方法。

0.2.4 字符串补充知识

  1. StringBuilder和StringBuffer

    • Java StringBuffer 和 StringBuilder 类
    • 三者区别:

      String 长度大小不可变
      StringBuffer 和 StringBuilder 长度可变
      StringBuffer 线程安全, StringBuilder 线程不安全
      StringBuilder 速度快

  2. StringTokenizer

  3. StringJoiner(高效拼接字符串)(java.util.StringJoiner)

    • 基于StringBuilder,性能和它类似
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 优雅地输出每个一个数组的值在同一行,每个值用 空格 隔开,开始输出 , 最后输出 号。
      import java.util.StringJoiner;
      int[] a = new int[]{1,2,3,4,5}
      StringJoiner sj = new StringJoiner(" ",":","。");
      for(int i : a){
          sj.add(i);
      }
      System.out.println(sj.toString);
      
    • 在不需要指定 开头和结尾 时,使用String.join()更方便:
      String[] strArray = new String[]{"ni","zhen","hao","kan"};
      //字符串队列
      List<String> strList = new ArrayList<String>();
      //添加元素
      strList.add("ni");
      strList.add("zhen");
      strList.add("hao");
      
      //只能使用数组或者list
      String joiner = String.join(" ",names);
      

0.3 关于Stack

0.3.1 什么是Stack

  1. 介绍:

    • 栈是Vector的一个子类,它实现了一个标准的后进先出的栈。
    • 堆栈只定义了默认构造函数,用来创建一个空栈。 堆栈除了包括由Vector定义的所有方法,也定义了自己的一些方法。
  2. 所处的包:

    • java.util.Stack;
  3. 常用方法描述:(除了Vector的方法外)

  4. 补充说明

    • Stack继承于Vector,而Vector是List的实现类,所以Stack可以用List的一些方法。比如查询栈中数目,Stack.size()。

0.4 关于map在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 53
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值