华为机试题目菜鸟笔记C++&Java

华为机试菜鸟笔记C++&Java

1. 字符串最后一个单词的长度

#include<bits/stdc++.h>//万能头文件
using namespace std;
int main(){
    string s;
    while(cin >> s);
    cout << s.size();
    return 0;
}
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!"); 
    }
}
  • cin输入的机制,有空格会停止,系统把空格作为数据间的分隔符,整个英文句子会一个单词一个单词的读。非常巧妙的使用了cin的读取逻辑。
  • cin.getline()接收字符串,可以输入空格并输出。
  • https://baike.baidu.com/item/cin/23384763?fr=aladdin

2.计算某字符出现次数

#include<bits/stdc++.h>
using namespace std;
int main() {
    string s;
    getline(cin, s);//输入字符串
    char c = tolower(getchar());//字符小写
    uint16_t n = 0;
    for (auto i : s) {		//简单理解为 从第一个字符遍历
        if (tolower(i) == c) {
            ++n;
        }
    }
    cout << n << endl;
}
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!"); 
    }
}
  • tolower()是一种函数,功能是把字母字符转换成小写,非字母字符不做出处理。
  • getchar()函数的作用是从计算机终端(一般为键盘)获取一个无符号字符。
typedefint int16_t;
typedef unsigned int uint16_t;
  • uint16_t 这些数据类型中都带有_t, _t 表示这些数据类型是通过typedef定义的,而不是新的数据类型。也就是说,它们其实是我们已知的类型的别名。使用的原因:方便代码的维护。
  • https://blog.csdn.net/xiejingfa/article/details/50469045

3.HJ3 明明的随机数

#include<bits/stdc++.h>
int main(){
    int n;
    int a;
   //以数组下标来存储随机数,下标对应的数组值为1,来说明是否是存储的随机数
    while(~scanf("%d",&n)){//while(~scanf("%d",&n))<=>  while(scanf("%d",&n)!=EOF)
        int count[1001]={0};
        int i;
        for(i=0;i<n;i++){
            scanf("%d",&a);//&:引用或者指针、
            count[a]=1;
        }
        for(i=0;i<1001;i++){
            if(count[i]==1){
                printf("%d\n",i);
            }
        }
    }
    return 0;
}
}
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!"); 
    }
}

while(~scanf("%d",&n)) <=> while(scanf("%d",&n)!=EOF)

-1在内存中:1111 1111(八个一),原理如下:设(1111 1111)为原码,如果要想知道原码的十进制数是多少,需要做一下处理。

先判断:当最高位是0时,表示正数,正数的原码=反码=补码当最高位为1时,表示负数,负数的原码取反为反码,然后反码加一为补码,补码就是这个负数的绝对值。
,第一步,取反;最高位为符号位,把(1111 1111)取反就为反码(0000 0000)8个0,
第二步,反码加一;加1等于(0000 0001),这儿等到的(0000 0001)就是(1111 1111)的补码,补码(0000 0001)的十进制是1,这儿的1就是这个负数的绝对值。完毕。

4.HJ4 字符串分隔.

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string str;
    while (cin >> str)
    {
        // 补0
        int len = str.size();
        if (len % 8 != 0)
        {
            int count = 8 - len % 8;
            str.append(count, '0');//添加几个相同的字符:
        }

        // 按格式输出
        int newLen = str.size();
        for (int i = 0; i < newLen; i += 8)
        {
            cout << str.substr(i, 8) << endl;//从i开始输出8个长度的字符串
        }
    }
    return 0;
}
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!"); 
    }
}

-C++ string append方法的常用用法

value = atoi(dateStr.substr(i, 2).c_str());

里面包含三个函数,分别是atoi(),substr(),c_str().

百度:

atoi()函数原型为: int atoi(char *str),用途是将字符串转换成一个整数值,str是待转化成整数值的字符串.成功则返回转化后的整数值,失败返回0.
substr()函数原型为:basic string::substr(string,start,length),也可把string移到外面,为string &a,a.substr(start,length),其中a是待截取的字符串,start表示从截取开始的前一位,length表示截取长度,例如string &a="hello world",则a.substr(6,5)=world.
c_str()函数原型为:const char c_str(),如果要将string对象,转化为char对象,c_str()提供了这样一种方法,它返回一个客户程序可读不可改的指向字符数组的指针。

所以value=atoi(dateStr.substr(i,2).c_str())的作用就是,截取string型的对象dateStr,从第i个字符截取2个长度的,并转化为char*对象,然后将此字符串转换成一个整数值,赋值给value(value是int型).

5.HJ5 进制转换

#include<bits/stdc++.h>
using namespace std;
int main() {
    string str;
    while (cin >> str) {
        cout << stoi(str, 0, 16) << endl;
    }
}
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!"); 
    }
}

stoi()表示将字符串转换为整数 ,它是C ++ STL中的标准库函数,用于将各种格式(例如二进制,八进制,十六进制或字符串格式的简单数字)的给定字符串转换为整数。

句法:int stoi(字符串,起始位置,n进制),将 n 进制的字符串转化为十进制

6.HJ6 质数因子

360截图18200424709378

质数/素数:质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)。

质数因子:质因子(或质因数)在数论里是指能整除给定正整数的质数。根据算术基本定理,不考虑排列顺序下,每个正整数都能够以唯一的方式表示成它的质因数的乘积。下面求解某一个数的质因子的情况。

C ++中的sqrt(x)函数返回数字的平方根。x为int、double、float类型的非负参数

双单引号区别:"字符串"、'单字符'


import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        //创建扫描器对象
        Scanner scanner = new Scanner(System.in);
        //从键盘中接收输入
        long num = scanner.nextLong();
	//我们判断数 num 是不是质数时,没必要从 2 一直尝试到 num 此题中的大循环也大可不必写一个到 num 的循环,写到num的平方根即可,如果此时数字还没有除数,则可判定其本身是一个质数,没有再除下去的必要了,直接打印其本身即可
        long k = (long)Math.sqrt(num);
	//先求num的质数,
	//注意,num一直在变小,这就暗含了一个现象或者说理论吧,就是从小到大试:如果一个数已经不能整除2了,那么这个数肯定不能整除2的倍数;同理3也一样,所以整个循环能够保证一旦出现新的因数,其一定就是质数
        for (long i = 2; i <= k ; ++i) {
            while (num % i == 0) {
                System.out.print(i + " ");
                num /= i;
            }

        }
        System.out.println(num==1?"":num+"");
    }
}

学习Java Scanner及其方法

  1. next():next()方法将输入读取到空格字符。一旦遇到空格,它就返回字符串(不包括空格)。
  2. nextLine():与next()不同,nextLine()方法读取包括空格在内的整个输入行。当该方法遇到下一行字符\n时终止。

for循环中的++i和i++

7.HJ7 取近似值


import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        double number = in.nextDouble();
        System.out.println((int)(number + 0.5));
    }
}

8.HJ8 合并表记录

知识点1:
Java Map接口
Java HashMap

842b3184e9caf566a822b5845e9f8295_39c58e175efd2ba779280e8bd093902f
Java for-each循环(遍历循环/增强的for循环)
知识点2:
Java 基本数据类型及取值范围
解惑:
main主函数(主方法)里头的参数String[] args有啥作用?
int 和 Integer 的区别
int 和 Integer的区别主要体现在以下几个方面:

  • 数据类型不同:int是基础数据类型,而 Integer是包装数据类型;
  • 默认值不同:int的默认值是 0,而 Integer的默认值是 null;
  • 内存中存储的方式不同:int 在内存中直接存储的是数据值,而 Integer实际存储的是对象引用,当 new 一个 Integer 时实际上是生成一个指针指向此对象;
  • 实例化方式不同:Integer 必须实例化才可以使用,而 int 不需要;包装类的存在解决了基本数据类型无法做到的事情泛型类型参数、序列化、类型转换、高频区间数据缓存等问题。
  • 变量的比较方式不同:int 可以使用 == 来对比两个变量是否相等,而 Integer一定要使用 equals 来比较两个变量是否相等。

采用hash表存放数据就好了,每次输入查询是否有存在的key,存在就将value累加到表中,最后输出表。

import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int tableSize = scanner.nextInt();
        //使用HashMap类创建map,tablesize为table容量
        Map<Integer, Integer> table = new HashMap<>(tableSize);
        for (int i = 0; i < tableSize; i++) {
            int key = scanner.nextInt();
            int value = scanner.nextInt();
            //containsKey(key)检查指定的键Key是否在map中
            if (table.containsKey(key)) {
                table.put(key, table.get(key) + value);
            } else {
                table.put(key, value);
            }
        }
        //for-each循环增强的for循环,更易写和可读
        for (Integer key : table.keySet()) {//返回Map集合中存在的所有键的集合
            System.out.println( key + " " + table.get(key));
        }
    }
}

9.HJ9 提取不重复的整数

大知识点:java集合框架之间的关系和对应联系。

知识点:

  1. java集合框架

    Java集合框架最全详解

/ 在java中表示整除,整数和整数运算得到的一定是整数;只要有小数参与整除/得到的一定是小数。

有时间看:

细节代码优化

区分点:

集合框架与Collection(集合)接口:Collection接口是集合框架的根接口。 该框架还包括其他接口:Map和Iterator。 这些接口也可能具有子接口。​

361e3b21a0813b9b511efe104fd668d2_2243690-9cd9c896e0d512ed



&---Collection接口:单列集合,用来存储一个一个的对象
 	&---List接口:存储有序的、可重复的数据。  -->“动态”数组
             	(ArrayList、LinkedList、Vector)
 
	&---Set接口:存储无序的、不可重复的数据   -->高中讲的“集合”
        	(HashSet、LinkedHashSet、TreeSet)
	&---Queue接口:先进先出的方式存储与访问
&---Map接口:双列集合,用来存储一对(key - value)一对的数据   -->高中函数:y = f(x)
    (HashMap、LinkedHashMap、TreeMap、Hashtable、Properties)
Java Iterator 接口
在Java中,Iterator接口提供了用于访问集合元素的方法。

image

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (sc.hasNext()) {
            // 使用HashSet来判断是否是不重复的
	    //当执行add添加后会返回一个 boolean,如过插入成功则放回true反正则为false
            HashSet<Integer> hs = new HashSet<>();//默认容量将为 16,负载因子将为 0.75
            int target = sc.nextInt();//Scanner的方法
            while (target != 0) {
                int temp=target%10;
                if(hs.add(temp))
                    System.out.print(temp);
		// 除10能去掉最右边的数字,/ 在java中表示整除,整数和整数运算得到的一定是整数;只要有小数参与整除/得到的一定是小数。
                target/=10;
            }
            System.out.println();
        }
    }
}

知识点:

[StringBuffur]:见11题

StringBulider及其方法

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //逆序排列,StringBuilder(String str),并调用StringBuilder的reverse()将字符串翻转。
        StringBuilder stringBuilder = new StringBuilder(scanner.nextLine()).reverse();
        String str = stringBuilder.toString();//j转换为String对象。
        //结果集
        StringBuilder result = new StringBuilder();

        for (int i = 0; i < str.length(); i++) {
	//indexOf()   返回字符串中指定字符/子字符串首次出现的索引。
	//charAt()	返回给定索引处的字符
            if (str.indexOf(str.charAt(i)) == i) {
		//append(obj)添加任意类的字符串,并返回当前对象(StringBuilder)
                result.append(str.charAt(i));
            }
        }
        System.out.println(result.toString());
    }
}


10.HJ10 字符个数统计

知识点:

  1. Java BitSet类:Bitset类创建一种特殊类型的数组来保存位值。BitSet中数组大小会随需要增加。

    BitSet就是位图,它的值只有1和0。内部是基于long[]实现的,long是8字节(64位),所以Bitset最小是64位,每次扩大一次扩大64位,即内部大小是64的倍数。每次BitSet新增加一个数字时,就将该位置为1。也就是说BitSet并不直接存储每个数据,而是存储数字是否存在过(1表示存在,0表示不存在)。

  2. 字节(byte)、位/比特(bite)、字符之间的关系。

    1. ​**bit比特/位**:二进制的每一个0/1 位,计算机内部数据储存的最小单位。

    2. ​**byte字节**:字节是计算机中最小的存储单元
      计算机中 数据处理 的基本单位,任何数据都是以字节​的方式存储。
      一个byte​(字节) = 8个bit​(位)即0000-0000,8个二进制位。

    3. ​**char字符 :占用2个byte(字节)**

    4. Java--位、字节、字符、字符编码、数据存储单位 & 电脑的32位和64位的区别是什么呢

      1. c7539722e8d9d1de46ab4c5899403855_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lfcl9vX25fTV9hX24,size_16,color_FFFFFF,t_70

      2. 大小关系:bit(位/比特) < byte(字节) < kb(千字节) < MB(兆字节) < GB(吉字节) < TB(太字节) <.....

        435816a4b774acdda2148db28dbb3564_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDEyMTk2Ng,size_16,color_FFFFFF,t_70

  3. A?B:C​ 其实为Java中的三元运算符,表示条件判断语句,对布尔类型的语句进行判断,即 A ? B : C,表示:如果语句A为真,则执行语句B,如果语句A为假,则执行语句C。

凡是涉及到去重统计都可以用位图实现。因为每一个不同的数据只需要用二进制的一位存储即可,大大减小了统计所使用的存储空间

import java.util.Scanner;
import java.util.BitSet;
public class Main {
    public static void main(String[] args) {
        Scanner scannner = new Scanner(System.in);
        String str=scannner.next();
        //总共有128个字符。字需要用128位
        BitSet bitSet=new BitSet(128);//BitSet位图
        for(char c:str.toCharArray()){//toCharArray():将字符串转换为char数组
            //判断字符c是否已出现
            if(!bitSet.get(c)){/*boolean get(int index)
返回指定索引处的位值。自动类型转换。。。而且转成的int恰好就是该字符对应的ASCII码*/
                //未出现就设置为已出现
                bitSet.set(c);//void set(int index):将指定索引处的位设置为 true。
            }
        }
        //统计有多少字符出现过
        System.out.println(bitSet.cardinality());//int cardinality( ):返回此 BitSet 中设置为 true 的位数。
  
    }
}

11.HJ11 数字颠倒

知识点:

  1. StringBuffer与StringBuilder

    StringBuilder 和 StringBuffer 是一对兄弟,因为它们拥有同一个父类 AbstractStringBuilder,同时实现的接口也是完全一样,都实现了 java.io.Serializable, CharSequence 两个接口。

    那它们有什么区别呢?最大的区别在于 StringBuffer 对几乎所有的方法都实现了同步,StringBuilder 没有实现同步,如同样是对 AbstractStringBuilder 方法 append 的重写,StringBuffer 添加了 synchronized 关键字修饰,而 StringBuilder 没有。

    e31ee2214837ad81d1f02ff0f6785f7f_v2-13d53c27ad0f8b40ebdd500b6cb58149_1440w

    273d6ec8ee1386a554204dc1cb09617a_v2-d475140e2070aa414d4bb95403a62d7c_1440w

    所以 StringBuffer 是线程安全的,在多线程系统中可以保证数据同步,而 StringBuilder 无法保证线程安全,所以多线程系统中不能使用 StringBuilder。

    但是方法同步需要消耗一定的系统资源,所以 StringBuffer 虽然安全,但是效率不如 StringBuilder,也就是说使用 StringBuilder 更快。

    1. String、StringBuffer、StringBuilder 有什么区别?

      1、String 一旦创建不可变,如果修改即创建新的对象,StringBuffer 和 StringBuilder 可变,修改之后引用不变。

      2、String 对象直接拼接效率高,但是如果执行的是间接拼接,效率很低,而 StringBuffer 和 StringBuilder 的效率更高,同时 StringBuilder 的效率高于 StringBuffer。

      3、StringBuffer 的方法是线程安全的,StringBuilder 是线程不安全的,在考虑线程安全的情况下,应该使用 StringBuffer。

  2. 学习Java Scanner及其方法

    1. next() 和 nextLine()的区别``​(可以输入数值型数据,返回值为String)

      1. String next() ​​:next()方法不能得到带有空格的字符串。一旦遇到空格,它就返回字符串(不包括空格)。
      2. String nextLine()​:与next()不同,nextLine()方法读取包括空格在内的整个输入行。当该方法遇到下一行字符\n时终止。
    2. hasNext() 和 hasNextLine() 的区别``​(返回值为Boolean)

      1. boolean hasNext()​:断接下来是否有非空字符.如果有,则返回true。
      2. boolean hasNextLine()​:根据行匹配模式去判断接下来是否有一行(包括空行),如果有,则返回true。
    3. 总结:采用hasNextXxxx() 的话,后面也要用nextXxxx()

      如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持,但是在输入之前最好先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取:

      采用hasNextXxxx() 的话,后面也要用nextXxxx(): 比如前面用hasNextLine(),那么后面要用 nextLine() 来处理输入; 后面用 nextInt() 方法的话,那么前面要使用 hasNext()方法去判断.

      image

      附上java如何在输入空时让scanner类自动结束

         public static  void main(String[] args){
              Scanner sc = new Scanner(System.in);
      
              while (sc.hasNextLine()){
                  String str = sc.nextLine();
                  if(str.isEmpty()){
                      break;
                  }
                  System.out.println(str);
              }
      
          }
      
      

      ​​

菜鸟随记:

  • 使用一下java中的注释标签

/**
 * @author PickUpShells
 * @version 1.0.0
 * @ClassName HW11.java
 * @Description 数字颠倒
 * @createTime 2022年01月19日 11:51:00
 */
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        String str =in.nextLine();//可以输入int类型,会被转换为字符串,以/n(回车)未结束符
        StringBuffer strb=new StringBuffer(str);//StringBuffer比StringBuilder略慢但是线程安全
        strb.reverse();//字符串顺序翻转
        System.out.println(strb.toString());
  
    }
}


12.HJ12 字符串反转

知识点:

  1. Stack

  2. System.out.print和System.out.println区别

    1. 参数有区别:

      System.out.println() 可以不写参数

      System.out.print(参数) 参数不能为空.必须有

    2. 效果有区别

      println :会在输出完信息后进行换行,产生一个新行

      print: 不会产生新行

    3. println更简洁, print更灵活

      print可以后面跟"\n"来达到和println一样的效果也可以跟"\t" 制表符, 等.

  3. 对象定义中的<>

    相关:java泛型

    Stack<Type> stacks = new Stack<>();
    //<Type>数据类型,代表该Stack中只能放入Type类或者其子类的实例。
    //? 第二个<>也许指的是大小
    

菜鸟随记:改版了,更换为有序列表

import java.util.Scanner;
import java.util.Stack;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Stack stack=new Stack();
        String str=in.nextLine();
        for(int i=0; i< str.trim().length();i++){//trim():删除任何前导(开始)和尾随(结束)空格,这里没有也可以
            stack.push(str.charAt(i));///push():将元素添加到堆栈的顶部
        }
        while(!stack.empty()){//empty():检查堆栈是否为空
            System.out.print(stack.pop());//pop():从堆栈顶部删除元素,并返回该元素
        }
    }
}

13.HJ13 句子逆序

知识点:

  1. Java String split()方法在指定的正则表达式处分割字符串,并返回子字符串数组。

    string.split(String regex, int limit)
    
    • regex - 字符串在此正则表达式处分割(可以是字符串)
    • limit (可选)-指定生成的子字符串的数量

    如果未传递参数limit,则split()返回所有可能的子字符串。

  2. Java正则表达式基础入门知识

菜鸟随记:初次接触正则表达式,之前也听说,见过但是他认识我我不认识他了。ε=(´ο`*)))唉

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str=in.nextLine();
        String s[]=str.split(" ");//split():将字符串拆分为指定的字符串(正则表达式)
        for(int i=s.length-1;i>=0;i--){
            if(i!=0)
                System.out.print(s[i]+" ");
            else
                System.out.print(s[i]);       
        }
    }
}

14.HJ14 字符串排序

知识点:

  1. 了解Java 异常(Exceptions)

    1. IOException :IOException也称为检查异常。它们由编译器在编译时检查,并提示程序员处理这些异常。
    2. RuntimeException:一个运行时异常发生由于编程错误。它们也称为​非检查异常​。这些异常不在编译时检查,而是在运行时检查。
  2. Java 流(Stream)、文件(File)和IO

    1. 一个流被定义为一个数据序列。输入流用于从源读取数据,输出流用于向目标写数据。下图是一个描述输入流和输出流的类层次图。

      df1ce23162c2488ebe2f6943df0b3d87_iostream2xx

    2. BufferedReader InputStreamReader

      1. br.readLine():read() 方法从控制台读取一个字符,或者用 readLine() 方法读取一个字符串。
      2. br.close():关闭缓冲的读取器,调用close()方法后,我们将无法使用读取器读取数据。
    3. InputStreamReader.ready()

      通知此流是否已准备好被读取。

      如果下一读取保证不会阻塞输入,该方法返回true,否则返回false。

  3. Integer.parseInt

    将字符串参数作为有符号的十进制整数进行解析。

    如果方法有两个参数, 使用第二个参数指定的基数(进制数),将字符串参数解析为有符号的整数。

  4. .forEach(System.out::println);

    1. Java Lambda 表达式//? 没看

      Java8 推出了属于Java的lambda表达式,与一众的 => 不同,Java选择了 -> 做为箭头符号。ambda表达式的基本格式:()->{}

    2. Arrays.stream(ss).sorted().forEach(System.out::println);

    3. list.forEach(System.out::println);

    4. .forEach()

    5. 函数式接口

    6. ::是什么,怎么使用

  5. pq.offer(s);

菜鸟随记:这个解法完全超出我知识范围了,呜呜呜。知识点太多了,看了一遍好像啥也没记住o(╥﹏╥)o,尤其是这个lambda表达式和.forEach()

import java.util.*;
import java.io.*;

public class Main {
    // API中的sort方法大多使用快排或者归并排序;
    // stream可以更方便写代码,但在不同数据量但情况下效率不同,姑且可以认为更耗时

    //主函数调用实现方法解决问题
    public static void main(String[] args) throws IOException {

        withArraysAPI();
        //withComparator();
        //withPriorityQueue();
    }
    //方法1:调用API实现
    public static void withArraysAPI() throws IOException {
        //从输入流中读取并存储数组中的字符串
        //读取控制台输入:Java 的控制台输入由 System.in 完成。为了获得一个绑定到控制台的字符流,你可以把 System.in 包装在一个 BufferedReader 对象中来创建一个字符流。
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //Integer.parseInt br.readLine()
        int n = Integer.parseInt(br.readLine());
        String[] ss = new String[n]; //?n
        for (int i = 0; i < n; ++i) {
            ss[i] = br.readLine();
        }
        br.close();
        // use stream to sort and output strings, which may use more time
        Arrays.stream(ss).sorted().forEach(System.out::println);

        // 或许, 使用 Arrays.sort(Object[] a) and for loop to output, which may use less time
    }
    //方法二: 使用PriorityQueue
    public static void withPriorityQueue()throws IOException {
        // read and store strings in a priority queue from input stream
        PriorityQueue<String> pq = new PriorityQueue<>();
        //BufferedReader InputStreamReader(System.in)
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        br.readLine();//ReadLine:read the first line, but the number will not be used.
        String s;
        while ((s = br.readLine()) != null) {
            pq.offer(s);//pq.offer(s)
        }
        br.close();
        //输出
        while (!pq.isEmpty()) {
            System.out.println(pq.poll());//pq.poll()
        }
    }
    //方法三: 使用list并自己实现Comparator
    public static void withComparator() throws IOException {
        // read and store strings in a list from input stream
        List <String> list = new ArrayList<>();
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        br.readLine();// 读取第一行,但将不使用该数字。
        String s;
        while ((s = br.readLine()) != null) {
            list.add(s);
        }
        br.close();
        //sort with self defined comparator
        list.sort((s1, s2) -> {
            int i = 0;
            while (i < s1.length() && i < s2.length()) {
                if (s1.charAt(i) > s2.charAt(i)) {
                    return 1;
                } else if (s1.charAt(i) < s2.charAt(i)) {
                    return -1;
                } else {
                    i++;
                }
            }
            return s1.length() - s2.length();
        });
        // indeed, default comparator works for this case
        // list.sort(null);
        // or you may use Collections.sort method to avoid null
        // Collections.sort(list);

        //输出
        list.forEach(System.out::println);//?::

    }

}

15.HJ15 求int型正整数在内存中存储时1的个数

知识点:

  1. num&1:num与1做按位与,可以判断num的奇偶性。

    按位与结果取决于num最后一位,如果num最后一位是1,则结果为1,反之结果为0。
    if( (n&1)==1 ) 判断num最后1位是否为1,可以用来判断奇偶性。

    1. 举例:num=3的话
      3与1的与运算就是(先写成2进制,然后同位比较,都为1时此位为1,否则为0):
      11 & 01 = 01
      因此 3与1的与运算就是1

    2. 拓展:位运算——按位与(&)、按位或(|)、按位异或(^)

      1. 按位与(&)

        两个数进行按位与运算时,先将其分别换算成二进制数再进行运算,按位与简单的理解就是同位上的两个数只有同为真时则真,一假则假,1为真,0为假

        示例:17&23结果为十进制就是17

        0000 0000 0001 0001(17)

        0000 0000 0001 0111(23)
        ——————————
        0000 0000 0001 0001(17)

      2. 按位或(|)

        同上方式,只是要求是一真为真,同假才假,只要有一个为1则为1,只有都是0的时候才为0,同样用刚才的例子17与23进行按位或运算

        示例:17|23=23

        0000 0000 0001 0001(17)

        0000 0000 0001 0111(23)
        ——————————
        0000 0000 0001 0111(23)

      3. 取反(~)

        每个位上都取相反值,1变成0,0变成1。

        0000 0000 0001 0001(17)

        1111 1111 1110 1110(~17)

        所以:~17 =1111 1111 1110 1110

      4. 按位异或(^)

        同为假,异为真,还是17和23

        0000 0000 0001 0001
        0000 0000 0001 0111
        ——————————
        0000 0000 0000 0110
        所以:17^23=0000 0000 0000 0110
        总结:任何数与0异或,结果都是其本身。利用异或可以实现交换算法,例:

      5. 左移(<<)

        将一个数各二进制位全部向左移动若干位。

        示例:17<< 2 =0000 0000 0100 0100 =68

        左移一位的结果就是原值乘2,左移两位的结果就是原值乘4。

      6. 右移(>>)

        将一个数各二进制位全部向右移动若干位。

        示例:17 >> 2 =0000 0000 0000 0100 = 4

        右移一位的结果就是原值除2,右移两位的结果就是原值除4,除了以后没有小数位的,都是取整。

菜鸟随记:

比较简单,缓解一下我焦虑的心情:真不错啊、真不错...

先把十进制数字转成二进制数字的字符串,再将字符串中的“0”全部替换为空,字符串的长度就是1的个数。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int num = in.nextInt();
        String str = Integer.toBinaryString(num);
        String newStr = str.replaceAll("0", "");
        System.out.println(newStr.length());
    }
}
import java.util.Scanner;
 
public class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int num = in.nextInt();    //读取数字
        int n = 0;    //计数变量
        for(int i=0; i < 32; i++){
            if((num&1) == 1)    //如果末位为1则计数
                n++;
            num = num >>> 1;    //无符号右移
        }
        System.out.println(n);
    }
}


知识点:

菜鸟随记:


知识点:

菜鸟随记:


16.HJ16 购物单

知识点:

  1. 0\1背包问题:听懂不翻车系列之--背包问//? 待完成

    1. 第一节课:0/1背包问题

      1. 基本型:归纳得出,存储了所有的决策结果

        image

      2. 完全型:由上推下,滚动数组1行(空间压缩:优化空间复杂度)

        image

    2. 第二节课:

菜鸟随记:遇到的第一个难题,之前都不算难,呜呜呜。

  1. 本题为变形的01背包:题目提示

    1. 物品数组:

      物品\属性 0是价格 1是重要度 2是主附件 3是附件1 4是附件2
      ……
      i物品编号
      ……
    2. 背包数组:money+1是元素个数==数组下标money

      j剩余的钱 价值*重要度
      money+1
      ……

      ……
      0
    3. 几种选择情况

      一. 只买主件

      二. 买主件和第一个附件

      三. 买主件和第二个附件

      四. 买主件和两个附件

      五. 什么都不买

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int money = sc.nextInt();//有多少钱
        int num = sc.nextInt();//物品个数
        //0是价格,1是重要度,2是主附件,3是附件1,4是附件2.
        int[][] goods = new int[num + 1][5];

        for (int i = 1; i <= num; i++) {
            int v = sc.nextInt();
            int p = sc.nextInt();
            int q = sc.nextInt();
            goods[i][0] = v;//价格
            goods[i][1] = p;//重要度
            goods[i][2] = q;//主附件
            if (q != 0) { //如果是附件,往对应主件的3或4里面填该附件的序号
                if (goods[q][3] == 0) { //如果已经是附件1了则标记为附件2
                    goods[q][3] = i;
                } else {
                    goods[q][4] = i;
                }
            }
        }
	/*
        for (int i = 0; i <= m; i++) {
            System.out.println(Arrays.toString(goods[i]));//这里可看下物品数组
        }
	*/  


        int[]vw = new int[money + 1]; //dp数组的简化版(结合视频理解)

        for (int i = 1; i <= num; i++) {
            if (goods[i][2] == 0) { //如果是主件
                //01背包用倒序(结合视频理解)
                for (int j = money; j >= goods[i][0]; j--) {
                    //单主件;vw[j-goods[i][0]]:不拿上一个物品的满意度
                    vw[j] = Math.max(vw[j], vw[j - goods[i][0]] + goods[i][0] * goods[i][1]);
                    //有附件1:
                    if (goods[i][3] != 0 && j >= goods[i][0] + goods[goods[i][3]][0]) {
                        vw[j] = Math.max(vw[j], vw[j - goods[i][0] - goods[goods[i][3]][0]] +
                                         goods[i][0] * goods[i][1] + goods[goods[i][3]][0] * goods[goods[i][3]][1]);
                    }
                    //有附件2
                    if (goods[i][3] != 0 && j >= goods[i][0] + goods[goods[i][4]][0]) {
                        vw[j] = Math.max(vw[j], vw[j - goods[i][0] - goods[goods[i][4]][0]] +
                                         goods[i][0] * goods[i][1] + goods[goods[i][4]][0] * goods[goods[i][4]][1]);
                    }

                    //有附件1和附件2:
                    if (goods[i][4] != 0 && j >= goods[i][0] + goods[goods[i][3]][0] + goods[goods[i][4]][0]) {
		    	vw[j] = Math.max(vw[j], vw[j - goods[i][0] - goods[goods[i][3]][0] - goods[goods[i][4]][0]] + 
					goods[i][0] * goods[i][1] + goods[goods[i][3]][0] * goods[goods[i][3]][1] + 
						goods[goods[i][4]][0] * goods[goods[i][4]][1]);
                    }
                }
            }
            //System.out.println(Arrays.toString(vw));//这里可看每一行dp数组
        }
        System.out.println(vw[money]); //dp数组最后一位即答案
    }
}


HJ17 坐标移动

知识点:

  1. 正则表达式-菜鸟教程//? 没看呢

  2. Java continue语句

    Java中的continue语句跳过循环的当前迭代(for,while,do…while等),程序的控制权移到循环的末尾。

    8c227f9a8f55da13a8448f6baf1777d9_how-continue-statement-works_0961308435fbc1afa80e4dddac9ecf998_nested-while-loop-continue

    continue语句几乎总是在(if ... else语句)决策语句中使用。它的语法是:

    continue;
    
  3. Java break语句

    1. Java中的break语句立即终止循环,程序的控制权移至循环后的下一条语句。
    2. 5132262e328a418662bf67e829995a91_java-break-statement-works3798cf37b58df8b3297787358852ce28_nested-while-loop-break
  4. String的方法

    1. String.substring():返回给定字符串的子字符串

      string.substring(int startIndex, int endIndex)//下标从0开始
      
    2. String.charAt():返回给定索引处的字符

    3. String.split():将字符串拆分为指定的字符串(正则表达式)

  5. Integer.valueof()

    valueOf() 方法用于返回给定参数的原生 Number 对象值,参数可以是原生数据类型, String等。

    **Integer valueOf(String s):**返回保存指定的 String 的值的 Integer 对象。

    该方法是静态方法。该方法可以接收两个参数一个是字符串,一个是基数。

菜鸟随记:第二次碰到正则表达式了,

复杂度分析

  • 时间复杂度:O(n)O(n)O(n),nnn为输入的字符串长度,不管是正则表达式的匹配还是计算数字,总体上最多遍历字符串每个字符

  • 空间复杂度:O(1)O(1)O(1),正则表达式空间为常数

import java.util.*;
import java.io.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader (new InputStreamReader(System.in));
        String[] in = bf.readLine().split(";");
        int x = 0;
        int y = 0;
        for (String s : in) {
            //不满足题目给定坐标规则
	    //合法字符就是ASDW中一个字母后面接上1位或者2位数字,正则表达式为"[WASD][0-9]{1,2}"
            if (!s.matches("[WASD][0-9]{1,2}")) { //[]:匹配包含的任一字符;{}:匹配至少 n 次,至多 m 次
                continue;//continue:跳到下一次循环;break:跳出当前所在循环
            }
            int val = Integer.valueOf(s.substring(1)); //valueOf()将参数转换为Integer类型;String.substring()返回给定字符串从指定下标开始的子字符串
            switch (s.charAt(0)) { //String.charAt():返回给定索引处的字符
                case 'W':
                    y += val;
                    break;
                case 'S':
                    y -= val;
                    break;
                case 'A':
                    x -= val;
                    break;
                case 'D':
                    x += val;
                    break;
            }
        }
        System.out.println(x + "," + y);
    }
}
#华为机试,emo了#
全部评论
楼主,借下楼楼,谢谢。考虑华为od吗?可以来联系我呀?大佬们😁😁,不考虑也请不问骂我。谢谢哦。
点赞 回复 分享
发布于 2022-08-04 18:06

相关推荐

点赞 评论 收藏
分享
评论
2
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务