招聘参加了好多笔试。记录一下这样子。真的就是菜鸟写代码,很多不对和不规范的地方欢迎指正。
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]; //对边界的判断
else dp[i]