牛客刷题记录(常见笔试题)

news2025/7/19 11:27:59

目录

一、Map的应用篇

乒 乓球筐

简单的错误记录

二、动态规划篇

计算字符串的编辑距离

年终奖

最长不含重复字符的子字符串

合唱团

三、数组篇

顺时针打印矩阵


一、Map的应用篇

乒 乓球筐

题目地址:乒乓球筐

小白代码

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNext()) { // 注意 while 处理多个 case
            String A = in.next();
            
            String B = in.next();
        
            Map<Character, Integer> map = new HashMap<>();

            for (int i = 0; i < A.length(); ++i) {
                if (!map.containsKey(A.charAt(i))) {
                    map.put(A.charAt(i), 1);
                }
                else {
                    int temp = map.get(A.charAt(i));
                    map.put(A.charAt(i), temp + 1);
                }
                
            }
            int[] arrB = new int[100];
            for (int i = 0; i < B.length(); ++i) {
                // System.out.println(B.charAt(i) - 'A');
                arrB[B.charAt(i) - 'A']++;
                
            }
            int flag = 1;
            for (int i = 0; i < B.length(); ++i) {
                if (map.containsKey(B.charAt(i))) {
                    int j = B.charAt(i) - 'A';
                    if (arrB[j] <= map.get(B.charAt(i))) {
                        // 符合要求什么也不做
                    }
                    else {
                        // 不符合要求就改变flag
                        flag = 0;
                    }
                }
                else {
                    flag = 0;
                }
            }
            if (flag == 1) {
                System.out.println("Yes");
            }
            else {
                System.out.println("No");
            }
            
            
        }
    }
}

扩展做法

// write your code here
// write your code here
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNext()) { // 注意 while 处理多个 case
            String temp = in.next();
            StringBuilder A = new StringBuilder(temp);
            String B = in.next();
            char[] find = B.toCharArray();
            int flag = 1;
            for (char ch : find) {
                // 不等于-1,说明该字符在A中
                int index = A.indexOf(String.valueOf(ch));
                if (index != -1) {
                    // 题目要求的是B中的字符在A中都有,并且在B中的数量不多于在A中的数量
                    // 我们就在遍历B中的过程,逐步的删除A中与B中相同的字符,如果从头到尾B中的字符都在A中
                    // 删除就是防止A中虽然有B中的字符,但没有B中的字符数量多
                    A.deleteCharAt(index); 
                }
                else {
                    flag = 0;
                }
            }
            if (flag == 1) {
                System.out.println("Yes");
            }
            else {
                System.out.println("No");
            }
           
            
            
        }
    }
}

简单的错误记录

简单的错误记录

 

思路:

将每一个数据都存入到HashMap中,最后输出的时候只输出8个即可

代码如下

import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Scanner;
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {

        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        HashMap<String, Integer> map = new LinkedHashMap<String, Integer>();
        String str = null;
        while ((str = bf.readLine()) != null) {
            String[] strs = str.split(" ");
            String[] split = strs[0].split("\\\\");  //根据\分割
            int LineNum = Integer.parseInt(strs[1]);
            String FileName = split[split.length - 1];
            //只保留最后16位
            if (FileName.length() > 16)
                FileName = FileName.substring(FileName.length() - 16);
            String key = FileName + " " + LineNum;
            //放入到HashMap中
            int Number = 1;
            if (map.containsKey(key))
                map.put(key, map.get(key) + 1);
            else {
                map.put(key, Number);
            }
        }
        int count = 0;
        for (String string : map.keySet()) {
            count++;
            if (count > (map.keySet().size() - 8)) //输出最后八个记录
                System.out.println(string + " " + map.get(string));
        }
    }
}

二、动态规划篇

计算字符串的编辑距离

计算字符串的编辑距离

import java.io.*; // BufferedReader需要用
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) throws IOException{
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String strA = null;
        // 注意 hasNext 和 hasNextLine 的区别
        while ((strA = bf.readLine()) != null) {
            String strB = bf.readLine();
            // f[i][j]表示把A字符串的前i个字符转换成字符串B的前j个字符,需要进行的编辑距离

            int lenA = strA.length();
            int lenB = strB.length();
            int[][] ret = new int[lenA + 1][lenB + 1];
            ret[0][0] = 0;
            for (int i = 0; i <= lenA; ++i) {
                ret[i][0] = i;
            }
            for (int j = 0; j <= lenB; ++j) {
                ret[0][j] = j;
            }

            // 状态转移方程:ret[i][j] = ret[i][j - 1] + 1 || ret[i][j] = ret[i - 1][j] + 1;
            /// ret[i][j] = ret[i - 1][j - 1] + 1;
            for (int i = 1; i <= lenA; ++i) {
                for (int j = 1; j <= lenB; ++j) {
                    // 这里有些特殊,因为我们的字符真正的数据是从0,下标开始的——》即0下标和我们的ret[1][1]对应
                    // 但我们这个ret[0][0]
                    if (strA.charAt(i - 1) == strB.charAt(j - 1)) { // 说明我们字符串A的第一个字符和我们字符串B的第一个字符相同ret[1][1] = 0;
                        ret[i][j] = ret[i - 1][j - 1];
                    }
                    else {
                        ret[i][j] = Math.min(Math.min(ret[i - 1][j], ret[i][j - 1]), ret[i - 1][j - 1]) + 1;
                    }
                }
            }
            System.out.println(ret[lenA][lenB]);
        }
    }
}

年终奖

题目链接:年终奖

import java.util.*;

/**
这个计算过程中有三个特殊情况

情况1:如果是起点,那么直接忽略即可
情况2:如果处在第一行,那么由于是第一行,所以从起点走,它只可能是向右不断走得到的
情况3:如果处在第一列,那么由于是第一列,所以从起点走,它只可能是向下不断走的到的
 */
public class Bonus {
    // 建立一个相同的矩阵board,board[i][j]表示从起点到i,j这一点中某条路径代表的礼物价值值总和
    // 但要注意我们这里一开始传的参数board只是表示这一点的礼物价值,还不是到达这一点的路径总价值——》是经过不断构建才形成的礼物价值总和数组board[i][j];
    public int getMost(int[][] board) {
        // write code here
        int row = board.length; // 行数
        int col = board[0].length;// 每一行有多少列
        // 先要把borad[0][j]第一行、board[i][0]第一列给构建好了,使得borad[i][0]、board[0][j]就代表从起点到这一列这个位置或者这一行这个位置的所获得的礼物总价值
        for (int i = 1; i < row; ++i) {
            board[i][0] = board[i - 1][0] + board[i][0];
        }
        for (int j = 1; j < col; ++j) {
            board[0][j] = board[0][j - 1] + board[0][j];
        }
        // 此时,第一行borad[i][0]、board[0][j]就代表从起点到这一列或者这一行的总价值
        // 接下来我们要构建中间的了(在第一行和第一列的基础上)
        for (int i = 1; i < row; ++i) {
            for (int j = 1; j < col; ++j) {
                // 对于这样一个棋盘,到达(i,j)这一点要么是上一行(i-1,j)向下移动一行得到,要么是前一列(i,j-1)向右移动一列得到
                board[i][j] = Math.max(board[i - 1][j], board[i][j - 1]) + board[i][j];  // board[i][j]代表了此时从起点到board[i][j]位置所经过路径所获得的礼物总价值
            }
        }
        return board[row - 1][col - 1];
    }
}

如果你对上面的board[i][j]代表的究竟是这一点的礼物价值,还是从起点到这一点所经过的路径的总价值不太清楚的话。

我们不妨另外构建一个矩阵gifts[i][j]来专门表示从起点到i,j这一点中某条路径代表的礼物价值值总和。

 思路分析:

 这道题属于贪心算法,但本质仍然是动态规划。对于这样一个棋盘,到达(i,j)这一点要么是上一行(i-1,j)向下移动一行得到,要么是前一列(i,j-1)向右移动一列得到

这个计算过程中有三个特殊情况

  • 情况1:如果是起点,那么直接忽略即可
  • 情况2:如果处在第一行,那么由于是第一行,所以从起点走,它只可能是向右不断走得到的
  • 情况3:如果处在第一列,那么由于是第一列,所以从起点走,它只可能是向下不断走的到的

其余情况均是即可向右走,也可以向下走

代码:

import java.util.*;

public class Bonus {
    public int getMost(int[][] board) {
        // write code here
        int row = board.length;
        int col = board[0].length;
        // gifts[i][j]表示从起点到i,j这一点中某条路径代表的礼物价值值总和
        int[][] gifts = new int[row][col];
        gifts[0][0] = board[0][0];
        for (int i = 1; i < row; ++i) {
            gifts[i][0] = gifts[i - 1][0] + board[i][0];
        }
        for (int j = 1; j < col; ++j) {
            gifts[0][j] = gifts[0][j - 1] + board[0][j];
        }
        
        for (int i = 1; i < row; ++i) {
            for (int j = 1; j < col; ++j) {
                // 对于这样一个棋盘,到达(i,j)这一点要么是上一行(i-1,j)向下移动一行得到,要么是前一列(i,j-1)向右移动一列得到
                gifts[i][j] = Math.max(gifts[i - 1][j], gifts[i][j - 1]) + board[i][j];  // board[i][j]代表此点上的礼物价值
                // gifts[i][j]代表从起点到i,j这一点所经过路径代表的礼物价值总和
            }
        }
        return gifts[row - 1][col - 1];
    }
}

最长不含重复字符的子字符串

  • step 1:dp[i]dp[i]dp[i]表示以下标i结尾的字符串最长不含重复子串的长度,用哈希表记录是否重复出现字符,并记录其下标位置。
  • step 2:遍历字符串,哈希表中没有出现过的就不是重复,因此考虑dp[i]=dp[i−1]+1,即在前一个字符的基础上加上它。
  • step 3:哈希表中出现过的,这是重复的字符,考虑i−map[s[i]],但是为了防止中间出现其他重复的字符,还是应该考虑它的前一个字符的基础,因此实际转移方程为dp[i]=min(dp[i−1]+1,i−map[s[i−1]])——map[s[i - 1]]
  • step 4:遍历过程中遇到的字符都要加入哈希表,同时维护最大的长度。
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param s string字符串 
     * @return int整型
     */
    public int lengthOfLongestSubstring (String str) {
        // write code here
        int[] dp= new int[str.length()];
        char[] s = str.toCharArray(); 
        dp[0] = 1; // dp[i]代表以s[i]结尾的的字符串的最长子字符串的长度
        Map<Character, Integer> map = new HashMap<>();
        map.put(str.charAt(0), 0);

        int res = 1, len = 0; // 当字符串只有一个字符,程序不会执行for循环,此时要进行特判
        for (int i = 1; i < str.length(); ++i) {
            if (!map.containsKey(str.charAt(i))) {
                dp[i] = dp[i - 1] + 1;
            }
            else {
                dp[i] = Math.min(dp[i - 1] + 1, i - map.get(str.charAt(i)));
                // dp[i] = i - map.get(str.charAt(i));
            }
            map.put(str.charAt(i), i);
            res = Math.max(dp[i], res);
        }
        return res;
    }
}

合唱团

牛客链接

import java.util.*;
import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException{
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String str = null;
        while((str = bf.readLine()) != null) {
            int n = Integer.parseInt(str);
            String num = bf.readLine();
            
            String[] nums = num.split(" ");
            int[] a = new int[nums.length];
            for (int i = 0; i < nums.length; ++i) {
                a[i] = Integer.parseInt(nums[i]);
            }
            
            String str2 = bf.readLine();
            String[] strs2 = str2.split(" ");
            int k = Integer.parseInt(strs2[0]);
            int d = Integer.parseInt(strs2[1]);
            
            long[][] maxVal = new long[n + 1][k + 1];
            long[][] minVal = new long[n + 1][k + 1];
            // maxVal[i][j]代表当最后一个是第i个同学,共选了j个同学所得到了最大能力值
            // 初始化
            for (int i = 1; i <= n; ++i) {
                maxVal[i][1] = minVal[i][1] = a[i - 1];
            }
            long ret = 0;
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= k; ++j) {
                    // 约束条件
                    for (int m = i - 1; m >= Math.max(i - d, 1); --m) {
                        maxVal[i][j] = Math.max(maxVal[i][j], Math.max(maxVal[m][j - 1] * a[i - 1], minVal[m][j - 1] * a[i - 1]));
                        minVal[i][j] = Math.min(minVal[i][j], Math.min(minVal[m][j - 1] * a[i - 1], maxVal[m][j - 1] * a[i - 1]));
                    }
                }
                ret = Math.max(ret, maxVal[i][k]);
            }
            System.out.println(ret);
            
        }
    }   
}

三、数组篇

顺时针打印矩阵

解题思路

1、声明四个变量,分别为左界限 L,右界限 R,上界限 T,下界限 B。

2、先从左往右遍历,然后从上到下,从右往左,最后从下往上。循环这个操作,每次从左往右遍历完,T += 1,说明最上面这一行已经遍历过了,上界限 T 应该往下移了;从上往下遍历完, R -= 1,说明最右边这一列已经遍历过了,右界限 R 应该往左移了;其他遍历操作也是如此。当四个界限中,T 和 B,或者 L 和 R 碰撞在一起,说明遍历完成,退出循环。

3、值得注意的是,需要考虑非方阵的情况,比如矩阵 A[3][4],因为行数比列数少,T 和 B 碰撞时 L 和 R 仍未碰撞,若此时还在循环体内,会继续执行遍历操作。所以在循环体内,需要时刻监控界限碰撞的情况。

 

 

 

 

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
       int t = 0;
       int b = matrix.length - 1, row = matrix.length;
       int l = 0;
       int r = matrix[0].length - 1, col = matrix[0].length;
       ArrayList<Integer> list = new ArrayList<>();
       while (t <= b && l <= r) {
           // 从左到右, 需要注意我们的边界都是动态变化的
           for (int i = l; i <= r; ++i) {
               list.add(matrix[t][i]);
           }
           ++t; // 第一行遍历完了,上边界要发生变化
           if (t > b || l > r) break;
           // 从上到下
           for (int j = t; j <= b; ++j) {
               list.add(matrix[j][r]);
           }
           --r;
           if (t > b || l > r) break;
           // 从右到左
           for (int i = r; i >= l; --i) {
               list.add(matrix[b][i]);
           }
           --b;
           if (t > b || l > r) break;
           // 从下到上
           for (int j = b; j >= t; --j) {
               list.add(matrix[j][l]);
           }
           ++l;
       }
       return list;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/18369.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一次就能释放大量Mac内存空间的方法,你用过哪种?

清理Mac内存空间对Mac的运行速度有着非常大的好处&#xff0c;所以合理释放Mac内存空间是广大用户常做的一件事。那么小编整理了一些能够一次性大量释放Mac内存空间的方法&#xff0c;大家常用的是哪一种呢&#xff1f;欢迎一起交流哦~以下&#xff1a; 一、清理MAC缓存&#x…

微信小程序|从零动手实现俄罗斯方块

&#x1f4cc;个人主页&#xff1a;个人主页 ​&#x1f9c0; 推荐专栏&#xff1a;小程序开发成神之路 --【这是一个为想要入门和进阶小程序开发专门开启的精品专栏&#xff01;从个人到商业的全套开发教程&#xff0c;实打实的干货分享&#xff0c;确定不来看看&#xff1f; …

[Linux]----进程间通信之管道通信

文章目录前言一、进程间通信目的二、进程间通信发展三、进程间通信分类四、管道1. 匿名管道2. 管道内核代码3. 站在文件描述符角度-深度理解管道4. 站在内核角度-管道本质5. 管道的特征总结五、命名管道1. 创建命名管道总结前言 首先我基于通信背景来带大家了解进程间通讯&…

HTTP协议详细总结

目录 1.HTTP协议是什么? 2.什么叫做应用层协议 3.HTTP协议的工作流程 4.HTTP报文格式 请求报文: 响应报文: 5.URL 6.方法的认识 1.GET 2.POST 3.GET和POST的区别 4.其他方法 7.报头的认识 用户登陆过程: 8.状态码的认识 9.HTTPS 9.1HTTPS是什么? 9.2HTTPS的…

现代c++中实现精确延时方法总结

程序中实现延时有很多种办法&#xff0c;但是有些不建议用。比如还在用sleep()或者空转计数的方式延时&#xff1f;要么移植性不好&#xff0c;要么不够精确且效率太低。这里总结下现代c中推荐的一种实现精确延时的方法。 之前的一些用法 粗暴空转 long wait 0; while(wait…

十二、Mysql的索引

Mysql的索引十二、Mysql的索引一、什么是索引二、常见索引的种类(算法)三、B树 基于不同的查找算法分类介绍1、B树结构2、B-树四、索引的功能性分类1、辅助索引(S)及构建B树结构2、聚集索引(C)及构建B树结构3、聚集索引和辅助索引构成区别4、关于索引树的高度受什么影响五、索引…

Vue快速入门一:官网、下载、定义变量

Vue官网&#xff1a;Vue.js - 渐进式 JavaScript 框架 | Vue.js Vue2中文文档&#xff1a;Vue.js介绍 — Vue.jsVue.js Vue3中文文档&#xff1a;快速上手 | Vue.js Vue下载&#xff1a; Vue2下载&#xff1a; 引入Vue2版本&#xff1a;打开上面的中文文档&#xff0c;找到这…

Flink窗口及其分类-详细说明

文章目录&#x1f48e;Flink窗口的概念⚽窗口的分类&#x1faa9;窗口 API 概览⚾窗口分配器&#xff08;Window Assigners&#xff09;&#x1f603;&#x1f603;&#x1f603;&#x1f603;&#x1f603; 更多资源链接&#xff0c;欢迎访问作者gitee仓库&#xff1a;https:/…

Hive:BUG记录,错误使用动态分区导致的插入失败

1.场景 在Hive中&#xff0c;插入数据时可以指定动态分区&#xff0c;如果通过partition(day_partition)指定动态分区&#xff0c;而实际的select语句是直接把这个属性值写死了&#xff08;如‘2022-10-13’&#xff09;&#xff0c;就可以不需要指定hive变量set hive.exec.dy…

【牛客】四选一多路器

描述 制作一个四选一的多路选择器&#xff0c;要求输出定义上为线网类型 状态转换&#xff1a; d0 11 d1 10 d2 01 d3 00 信号示意图&#xff1a; 波形示意图&#xff1a; 输入描述&#xff1a; 输入信号 d1,d2,d3,d4 sel 类型 wire 输出描述&#xff1a; 输出信…

【信号处理】扩展卡尔曼滤波EKF(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

学习 MongoDB5 这一篇就够了

文章目录一、相关概念1.1、业务场景1.2、简介1.3、体系结构1.4、数据模型二、安装三、基本常用命令3.1、数据库操作3.2、集合操作3.3、文档基本CRUD1、插入2、查询3、更新4、删除3.4、分页查询3.5、更多查询3.6、小结四、索引4.1、概述4.2、类型4.3、管理操作4.4、索引的使用4.…

四十五、壁面函数理论及y+的确定

0. 前言 什么叫做壁面函数&#xff0c;为什么引入壁面函数的概念?? 因为流体无论流动&#xff0c;还是传热、传质都存在边界层。而之所以有壁面函数这个东西&#xff0c;根源就在于边界层理论。 1. 边界层理论 大家都知道什么是边界层理论&#xff0c;我们想要理解壁面函数…

美国这几年的人口死亡数据

2015年&#xff1a;总死亡271.20万&#xff0c;平均死亡年龄78.8 2016年&#xff1a;总死亡274.40万&#xff0c;平均死亡年龄78.6 2017年&#xff1a;总死亡281.35万&#xff0c;平均死亡年龄78.6 2018年&#xff1a;总死亡283.90万&#xff0c;平均死亡年龄78.7 2019年&#…

Java中的方法是什么?(Java系列2)

目录 前言&#xff1a; 1.什么是方法 2.方法的定义 3.方法调用的执行过程 4.实参和形参的关系 5.方法重载 6.方法签名 7.递归 8.关于“调用栈” 结束语&#xff1a; 前言&#xff1a; 在上一次博客中小编主要和大家分享了Java中的一些基础知识&#xff0c;与小编之前…

Python多任务编程

1.进程与多任务 1. 1 多任务的介绍 1.使用多任务能充分利用CPU资源&#xff0c;提高程序的执行效率&#xff0c;让程序具备处理多任务的能力。 2.多任务执行方式有两种&#xff1a; 并发&#xff1a;在一段时间内交替执行多个任务。 并行&#xff1a;在一段时间内真正的同…

第三周 青海之行——练练构图,培养你的摄影眼

目录3.1 油菜花海&#xff0c;怎么拍更好看&#xff1f;3.2 构图的元素&#xff1a;线条、形状、图案(一)3.3 构图的元素&#xff1a;光影、留白、框景(二)3.4 摄影构图 补充内容构图作业3.1 油菜花海&#xff0c;怎么拍更好看&#xff1f; 祁连山下的百里油菜花海 门源 雪山下…

冲冲冲!!!python计算机二级每日一套_8

文章目录一、选择题二、基本操作三、简单应用四、综合应用声明&#xff1a;例题均来源于网络&#xff0c;仅供学习笔记&#xff0c;若涉侵权请联系删除。所属练题来源于《小黑课堂》一、选择题 1、树的度为3&#xff0c;共有31个结点&#xff0c;但没有度为1和2的结点。则该树…

C++ Reference: Standard C++ Library reference: Containers: deque: deque: clear

C官网参考链接&#xff1a;https://cplusplus.com/reference/deque/deque/clear/ 公有成员函数 <deque> std::deque::clear C98 void clear(); C11 void clear() noexcept;清除内容 从deque中删除所有元素&#xff08;已销毁&#xff09;&#xff0c;使容器的size为0。…

MBIST BAP(Bist Access Port)直接访问接口(1)

More articles You can follow the official account&#xff1a;“IC练习生” IC民工不定期更新 BAP BAP会覆盖掉连接到BAP上的memory的一些默认操作模式; 通过消除串行配置控制器的shift cycle,大大缩短测试时间,代价是在BAP和控制器之间额外的连接; BAP的高级访问属性部分…