求解暗黑字符串(网易2017秋招)

问题描述:一个只包含‘A‘、‘B‘和‘C‘的字符串,如果存在某一段长度为3的连续子串中恰好‘A‘、‘B‘和‘C‘各有一个,那么这个字符串就是纯净的,否则这个字符串就是暗黑的。

例如:
BAACAACCBAAA 连续子串"CBA"中包含了‘A‘,‘B‘,‘C‘各一个,所以是纯净的字符串
AABBCCAABB 不存在一个长度为3的连续子串包含‘A‘,‘B‘,‘C‘,所以是暗黑的字符串

你的任务就是计算出长度为n的字符串(只包含‘A‘、‘B‘和‘C‘),有多少个是暗黑的字符串 (1 ≤ n ≤ 30)。

首先如果题目是如何判断一个字符串是暗黑(纯净)字符串,你会怎么解?

这个问题很简单,直接遍历判断连续的三个字符是否分别为ABC。额,而我想说的是有一个比较好的想法是

令A=2,B=3,C=5,如果某三个字母乘积为30,即这个字符串为纯净的字符串。尽管操作起来比直接判断连续3个字符串是否为ABC便利不了多少,但是我觉得这是一个比较好的想法。

讲回正题,现在是计算出长度为n的字符串,有多少个暗黑的字符串。

下面提供2种思路

思路1

当n=1时,3种情况,暗黑,

当n=2时,9种情况,暗黑。

当n=3时,第一个位置3种情况,第二个位置3种情况,而第三个位置则要考虑前2个位置,

如果前2个位置相同则第三个位置有三种选择,否则有2种选择。

所有有 3*(3*1+2*2)=21是暗黑的。

当n=4时,按照n=3的情况继续类推下去,假若第二个位置和第三个位置相同,第四个位置有3种选择,否则有2种选择。

所以有3*(3*(1+2)+2*(1*2+2))) = 51(如果看不明白可留言再解答)

如此类推可得出下列规律

当n>3,sum(n) = 3*(3*num3(n) + 2*num2(n))

num2(n) = 2*num3(n-1) + num2(n-1)

num3(n) = num3(n-1) + num2(n-1)

观察上面第一个式子3*(3*1+2*2)=21 ,num2(1)=2  num3(1)=1

这个思路主要是从式子里推出来的,也是比较常规的一个方法。

def dark1():
    dark = [3,9]
    num2 = 2
    num3 = 1
    for i in range(28):
        dark.append(3*(3*num3+2*num2))
        num3,num2 = num2+num3,2*num3+num2
    print(dark)

运行结果:

[3, 9, 21, 51, 123, 297, 717, 1731, 4179, 10089, 24357, 58803, 141963, 342729, 827421, 1997571, 4822563,

11642697, 28107957, 67858611, 163825179, 395508969, 954843117, 2305195203, 5565233523, 13435662249,

32436558021, 78308778291, 189054114603, 456417007497]

思路2

正如上面的思路1,我们可以分析出,每增加一个位置的字符,要使其保持暗黑的性质,只需要考虑前2个字符。

当前2个字符相同,那么第n个位置的取法有3种,否则有2种。

不妨设前2个字符相同的情况为s(n),前2个字符不同为d(n),那么我们可得出

sum(n) = 3*s(n-1) + 2*d(n-1) = 2*(s(n-1)+d(n-1)) + s(n-1) = 2*sum(n-1) + s(n-1)

因为前个字符要不就是d(n)要不就是s(n),所以d(n)+s(n)就等于sum(n),剩下的问题就是求解s(n-1)。

我们知道,对于s(n-1) AA 第三个字母只能跟之前一样AAA才能得到s(n),对于d(n-1) AB 第三个字符只有跟最后一个一样ABB才能得到s(n)

所以得出结论 s(n) = s(n-1) + d(n-1) = sum(n-1), s(n-1) = sum(n-2)

sum(n) = 2*sum(n-1) + s(n-1) = 2*sum(n-1) + sum(n-2)

def dark2():
    dark = [3,9]
    for i in range(28):
        dark.append(dark[-2]+2*dark[-1])
    print(dark)

运行结果:

[3, 9, 21, 51, 123, 297, 717, 1731, 4179, 10089, 24357, 58803, 141963, 342729, 827421, 1997571, 4822563,

11642697, 28107957, 67858611, 163825179, 395508969, 954843117, 2305195203, 5565233523, 13435662249,

32436558021, 78308778291, 189054114603, 456417007497]

时间: 2024-10-15 14:02:40

求解暗黑字符串(网易2017秋招)的相关文章

网易2017秋招编程题集合-牛客网

网易2017秋招编程题集合-牛客网 链接:https://www.nowcoder.com/questionTerminal/0147cbd790724bc9ae0b779aaf7c5b50来源:牛客网 如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列.例如: {1, 2, 1}, {15, 78, 78, 15} , {112} 是回文序列, {1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列. 现在给出一个数字序列,允许使用一

网易2017秋招笔试题3:最长公共子括号序列长度

[问题来源]网传的2017网易秋招笔试题 [问题描述] [算法思路] 下面的解题思路摘自  http://www.cnblogs.com/Atanisi/p/7500186.html 刚看到题我就想到暴力解,深搜出所有合法的括号序列,再依次比较公共子序列的长度,返回最长的.但是深搜一般和路径有关,这道题仅仅需要最大公共子序列的长度.而我们发现最大公共子序列的长度就是 s.size() - 1(当且仅当修改距离为 1 时 LCS 最大), 那么我们就想到,可以变换 s 中一个括号的位置,枚举所有的

网易2017秋招编程题集合_以下代码全部来自牛客网

如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列.例如:{1, 2, 1}, {15, 78, 78, 15} , {112} 是回文序列, {1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列.现在给出一个数字序列,允许使用一种转换操作:选择任意两个相邻的数,然后从序列移除这两个数,并用这两个数字的和插入到这两个数之前的位置(只插入一个和).现在对于所给序列要求出最少需要多少次操作可以将其变成回文序列. 链接:https://ww

网易2017秋招---优雅的点

做了这么多的编程题,其实我感觉题目只要找到思路 ,代码实现是非常容易的,因为程序语言不懂的地方可以百度, 而为一个题目找到思路却是没办法搜索的,除非题目是现成可以被搜索的 这个题目求解十分容易,用O(n2)的算法 进行遍历,找到非x,y轴上的的坐标点 就+=4  在x y轴就+=2 思考花了3分钟,编码2分钟,比较入门的题 package com.net163.question; import org.junit.Test; /** * Created by Administrator on 2

网易2017秋招编程题——回文序列 解题报告

Problem:https://www.nowcoder.com/question/next?pid=2811407&qid=46573&tid=6015849 如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列.例如: {1, 2, 1}, {15, 78, 78, 15} , {112} 是回文序列, {1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列. 现在给出一个数字序列,允许使用一种转换操作: 选择任意两个相邻的数,

美团点评2017秋招笔试编程题

美团点评2017秋招笔试编程题 1, 大富翁游戏,玩家根据骰子的点数决定走的步数,即骰子点数为1时可以走一步,点数为2时可以走两步,点数为n时可以走n步.求玩家走到第n步(n<=骰子最大点数且是方法的唯一入参)时,总共有多少种投骰子的方法. 题解: 写出前面的几个, 1 -> 1;   2 -> 2 ;  3 -> 4;   4 -> 8; 5 -> 16; 6 -> 32; 可以得到是 二的 n-1 次幂. #include <cstdio> int

好未来2017秋招笔试真题二 --牛客网

好未来2017秋招笔试真题二 --牛客网 链接:https://www.nowcoder.com/questionTerminal/ee5de2e7c45a46a090c1ced2fdc62355来源:牛客网 将一句话的单词进行倒置,标点不倒置.比如 I like beijing. 经过函数后变为:beijing. like I 输入描述: 每个测试输入包含1个测试用例: I like beijing. 输入用例长度不超过100 输出描述: 依次输出倒置之后的字符串,以空格分割 输入例子: I

网易2017春招笔试真题编程题集合题解

01 双核处理 题目 一种双核CPU的两个核能够同时的处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1kb,每个核同时只能处理一项任务.n个任务可以按照任意顺序放入CPU进行处理,现在需要设计一个方案让CPU处理完这批任务所需的时间最少,求这个最小的时间. 输入描述 输入包括两行:第一行为整数n(1 ≤ n ≤ 50)第二行为n个整数lengthi,表示每个任务的长度为length[i]kb,每个数均为1024的倍数. 输出描述输出一个整数,表示最少需

网易2017春招笔试真题编程题集合(8)——奇怪的表达式求值

常规的表达式求值,我们都会根据计算的优先级来计算.比如*/的优先级就高于+-.但是小易所生活的世界的表达式规则很简单,从左往右依次计算即可,而且小易所在的世界没有除法,意味着表达式中没有/,只有(+, - 和 *).现在给出一个表达式,需要你帮忙计算出小易所在的世界这个表达式的值为多少 输入描述: 输入为一行字符串,即一个表达式.其中运算符只有-,+,*.参与计算的数字只有0~9. 保证表达式都是合法的,排列规则如样例所示. 输出描述: 输出一个数,即表达式的值 输入例子: 3+5*7 输出例子