笔试题目记录


招聘参加了好多笔试。记录一下这样子。真的就是菜鸟写代码,很多不对和不规范的地方欢迎指正。

3.25微软

参加了3.25的微软笔试。。。菜鸟只配记录题目。(大哭)
当时没有写出来,(大哭),后来无意之间发现了大家有讨论这个题目,说是用动态规划。。。然后我也不懂,就上网查了查资料。。。根据大家的思路把这个题目写了一下。。。。
题目:
这个题目是第二题。别的题我……哎……不会。(大哭)

第二题:
给一个字符串,每次可以移除其中一个字符,或者移除一个回文子串,求 全部移除所需最少次数
例如:14315.先移除3,再移除141,再移除5,得到最少次数3.

参考思路的网页
思路摘抄如下:
我们用f[i][j]表示消灭第i个数到第j个数总最少需要多少次。可以分为下面多种情况:

1.如果i等于j,也就是单个元素的时候,那么需要一次。

2.如果我们最左边的单独消灭,那么就是1+f[i+1][j],例如下面自序列 1 2 3 3 2, f[1,5] = f[1, 1] + f[2, 4]

3.第三种情况,我们可以找到一个跟c[i]一样的元素,然后把这个序列一份为二,结果为f[i][j] = f[i + 1][k - 1] + f[k + 1][j],这个可能比较抽象,这里面一个问题,我们先举个形象的例子,例如 1 2 3 3 2 1 7 7 9 9, 那么我们可以找到跟第一个元素相同的,也就是第6个元素, f[1][10] = f[2][5] + f[7][10], 这里有人可能会提问,那么这两个1为什么不用消除了呢?因为它可以跟着f[2][5]的最后一次消除消掉!

4 . 对于第三种情况 一个最特殊的例子是 最前面的两位相同, 这个时候f[i + 1][k - 1]不存在!,所以f[i][j] =1 + f[i + 2][j],对应的例子就是 4 4 2 1 3

5.可能大家会有疑问,为什么要讨论把最左边的单读消灭,而不讨论最右边的单读消灭,假如最右边的单读消灭能够得到更有解,那么肯定存在于第三种情况。

综上所述,转移方程式如下:
在这里插入图片描述
然后我用JAVA写的:

import java.util.Scanner;

/*
* Writen : chl
* Date:27-03-2020
*/

public class Test1{
   
    public static void main(String[] args){
   
        Scanner sc= new Scanner(System.in);
        int n= sc.nextInt(); //数组长度
        int[] nums= new int[n];
        for(int i=0; i< n; i++){
   
            nums[i]= sc.nextInt(); //数组
        }
        //定义状态dp。dp[i][j]表示范围:数组下标为i到下标为j,包含i与j
        //有点像子字符串那种感觉
        //下面方便称呼就叫子字符串吧
        int[][] dp= new int[n][n];
        for(int i=0; i< n; i++){
   
            for(int j=0; j< n; j++){
   
                if(i > j) dp[i][j] = 0;
                else if(i == j) dp[i][j] = 1;
                else{
   
                    dp[i][j]= j -i +1;
                }
            }
        }
        for(int l =2; l <= n; l++){
    // 子字符串长度, 从2 到 n
            for(int i =0; (i +l -1) < n; i++){
    //i为开始的坐标
                int j = i +l -1; //j为结束坐标
                for(int k= i +1; k<= j; k++){
    //遍历子字符串
                    //以子字符串的NO.1数字为基础,后面的数字与NO.1数字比,只有两种可能:相等&不相等
                    if(nums[k] == nums[i]){
     //相等
                        if((k - i) == 1){
    //相等的挨着
                            if(k == j) dp[i][j] = 1; // 对边界的判断
                            else dp[i][j] = Math.min(dp[i][j], (dp[i + 2][j] + 1));
                        }
                        //相等的不挨着
                        else if(k == j) dp[i][j]= dp[i +1][j -1
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值