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

简介: 牛客刷题记录(常见笔试题)(下)

思路分析:

这道题属于贪心算法,但本质仍然是动态规划。对于这样一个棋盘,到达(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;
    }
}

合唱团

牛客链接

4c7496ed82f24dba9e80bf45f730fe28.png

f89fc6a8caee4f16941a8d4a6af3a503.png

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);
        }
    }   
}

三、数组篇

顺时针打印矩阵


fbc6f316f6ce4c7b9ce2ad4cfca14c59.png

解题思路

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



311e3b75d819419bb71a653517cdba2e.png

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


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


1a6f114562974f7d9eee855382669eb7.png

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



相关文章
|
监控 IDE 开发工具
【esp32c3配置arduino IDE教程】
设计用户操作界面,该设备具备简单易用的操作界面,外加显示屏SSD1306和旋转编码器进行显示和控制,用户后期可进行二次开发WiFi或蓝牙连接电脑或手机监控。
3057 0
|
4月前
|
人工智能 弹性计算 运维
【互动有礼 | 云故事探索】NO.16:阿里云弹性计算加速精准学 AI 教育普惠落地
在算力+教育的“化学反应”中,阿里云弹性计算正书写着 AI 时代的基础设施故事,以不变之初心,应万变之创新。
|
10月前
|
分布式计算 并行计算 调度
基于HPC场景的集群任务调度系统LSF/SGE/Slurm/PBS
在HPC场景中,集群任务调度系统是资源管理和作业调度的核心工具。LSF、SGE、Slurm和PBS是主流调度系统。LSF适合大规模企业级集群,提供高可靠性和混合云支持;SGE为经典开源系统,适用于中小规模集群;Slurm成为HPC领域事实标准,支持多架构和容器化;PBS兼具商业和开源版本,擅长拓扑感知调度。选型建议:超大规模科研用Slurm,企业生产环境用LSF/PBS Pro,混合云需求选LSF/PBS Pro,传统小型集群用SGE/Slurm。当前趋势显示Slurm在TOP500系统中占比超60%,而商业系统在金融、制造等领域保持优势。
2070 32
|
Prometheus 监控 Cloud Native
如何优化Java中的数据库连接池配置?
如何优化Java中的数据库连接池配置?
|
11月前
|
机器学习/深度学习 人工智能 自然语言处理
AI与代理IP:携手共创美好未来
在数字化浪潮中,人工智能(AI)与代理IP技术的融合正推动网络环境的智能化发展。AI凭借深度学习、自然语言处理等能力,结合代理IP的匿名性和灵活性,为网络安全、数据分析、内容分发等领域带来革命性变革。本文探讨两者协同作用,通过案例和代码展示其如何共同优化网络性能、保护隐私并提升效率,展望未来智能化、安全化的网络环境。 AI与代理IP的融合不仅提升了网络访问的效率与稳定性,还为智能风控、智能客服及全球内容分发网络(CDN)等应用提供了坚实支持。AI优化代理IP选择与调度,代理IP则保障AI应用的安全与隐私,二者相辅相成,共同推动全球化、智能化的发展趋势。
385 7
|
Ubuntu Shell Linux
docker安装tar包安装
docker安装tar包安装
2333 2
|
SQL 分布式计算 大数据
MaxCompute产品使用问题之如何修改字段类型
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
264 2
|
机器学习/深度学习 人工智能 架构师
超越年龄界限:程序员职业生涯的持续发展与转型策略
超越年龄界限:程序员职业生涯的持续发展与转型策略
324 0
|
SQL 流计算
Flink SQL 功能解密系列 —— 数据去重的技巧和思考
去重逻辑在业务处理中使用广泛,大致可以分两类:DISTINCT去重和FIRST_VALUE主键去重,两者的区别是DISTINCT去重是对整行数据进行去重,比如tt里面数据可能会有重复,我们要去掉重复的数据;FIRST_VALUE是根据主键进行去重,可以看成是一种业务层面的去重,但是真实的业务场景使用也很普遍,比如一个用户有多次点击,业务上只需要取第一条。
|
存储 定位技术 开发工具
Android 毕业设计 - 高仿今日头条新闻客户端(内附源码)
Android 毕业设计 - 高仿今日头条新闻客户端(内附源码)