【2021】腾讯秋招技术岗编程题之01串的价值

397 阅读2分钟

一.题目

给出一个只包含 0 和 1 的 01 串 s ,下标从 1 开始,设第 i 位的价值为 vali ,则价值定义如下:

  1. i=1时:val1 = 1

  2. i>1时:

2.1 若 si ≠ si-1 , vali = 1

2.2 若 si = si-1 , vali = vali-1 + 1

字符串的价值等于 val1 + val2 + val3 + ... + valn

你可以删除 s 的任意个字符,问这个串的最大价值是多少。

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 256M,其他语言512M

输入描述:

第一行一个正整数 n ,代表串长度。
接下来一行一个 01 串 s 。
1 ≤ n ≤ 5,000

输出描述:

输出一个整数代表答案

示例1

输入例子:

6
010101

输出例子:

7

例子说明:

删除后的串为0001或0111时有最大价值 

示例2

输入例子:

20
11111000111011101100

输出例子:

94

解答:

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        String s = in.next();
        char[] ss = new char[n + 1];
        for(int i = 0;i < n; i ++) {
            ss[i] = s.charAt(i);
        }
        int[] val = new int[n + 1];
        val[0] = 1;
        for(int i = 1;i < n;i ++) {
            val[i] = val[i - 1] + 1;
            int cnt = 1;
            for(int j = i - 1;j >= 0; j --) {  // 从后往前遍历
                if(ss[j] == ss[i])   cnt++;
                else {
                    val[i] = Math.max(val[i], val[j] + cnt *(cnt + 1) /2);   // 这是关键点
                }
            }
            val[i] = Math.max(val[i], cnt *(cnt + 1) /2);  // 如果后面连续的字符价值更大则更新
        }
        System.out.println(val[n-1]);
    }
}

在后面复习的时候,发现自己一直跳到一个坑里面,就是for(int j = i -;j >= 0;j--这个地方,这其实就像动态规划,我老是不记得这里是从后往前去遍历,如果你是从前往后这就会导致有的重复遍历到,所以答案就会变大。我就是总是觉得要从前往后,答案就会变大。