字节跳动编程题注解与思考

存在n+1个房间,每个房间依次为房间1 2 3...i,每个房间都存在一个传送门,i房间的传送门可以把人传送到房间pi(1<=pi<=i),现在路人甲从房间1开始出发(当前房间1即第一次访问),每次移动他有两种移动策略:
    A. 如果访问过当前房间 i 偶数次,那么下一次移动到房间i+1;
    B. 如果访问过当前房间 i 奇数次,那么移动到房间pi;
现在路人甲想知道移动到房间n+1一共需要多少次移动;
输入描述:
第一行包括一个数字n(30%数据1<=n<=100100%数据 1<=n<=1000),表示房间的数量,接下来一行存在n个数字 pi(1<=pi<=i), pi表示从房间i可以传送到房间pi。
输出描述:
输出一行数字,表示最终移动的次数,最终结果需要对1000000007 (10e9+7) 取模。
示例1
输入:
2
1 2
复制
输出:
4
复制
说明:
开始从房间1 只访问一次所以只能跳到p1即 房间1, 之后采用策略A跳到房间2,房间2这时访问了一次因此采用策略B跳到房间2,之后采用策略A跳到房间3,因此到达房间3需要 4 步操作。

2.思路与分析:
a.定义dp[i]为第一次到达i天所需要的最少的步数,那么我们要求的便是dp[n+1],数组在这里可以下标1到(n+1)来处理

b.dp[i]=dp[i-1]+1(传送门)+再次来到 i-1 + 1(下一步)

c.如何再次来到 i-1,我们知道回到了那个dp[p[i-1]] (第一次到i-1穿去的那个地方的步数)后访问次数又变奇数了(其他都是偶数,就相当于0),和他第一次从p[i-1]]到第一次到达i-1处一样(此处不用管i-1访问次数,因为我们只需要到达i-1即可,不关心在i-1处下一步的move)

d.dp[i]=dp[i-1]+1(传送门)+ dp[i-1]-dp[p[i-1]]+ 1(下一步)

第二题
https://blog.csdn.net/flushhip/article/details/79458502的题解+下面的代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
    long long t,n,k,d1,d2,a,b,c;//注意使用long ling
   cin>>t;
    while(t--)
    {
       cin>>n>>k>>d1>>d2;
        if(n%3!=0)//三者平衡 不平衡的直接pass
        {
           cout<<"no"<<endl;
           continue;
        }
        int flag=0;
        for(int i=-1;1>=i;i=i+2)//i =-1 和1进行正负d遍历
        {
            for(int i1=-1;1>=i1;i1=i1+2)//i =-1 和1进行正负d遍历 2*2四种状态
            {
                long long d11=d1*i;
                long long d22=d2*i1;
                a=(k-2*d11+d22)/3;
                b=(k+d11+d22)/3;
                c=(k+d11-2*d22)/3;
                if(a+b+c!=k||a<0||b<0||c<0)
                {
                    continue;
                }
                if(a>n/3||b>n/3||c>n/3)
                {
                    continue;
                }
                cout<<"yes"<<endl;
                flag=1;
                break;
            }
            if(flag==1)break;//一旦找到满足就退出
        }
        if(flag==0)
         cout<<"no"<<endl;;
    }
    return 0;
}
/*
a = (k-2*d1+d2)/3
 
b = (k+d1+d2)/3
 
c = (k+d1-2*d2)/3
*/

有一个仅包含’a’和’b’两种字符的字符串s,长度为n,每次操作可以把一个字符做一次转换(把一个’a’设置为’b’,或者把一个’b’置成’a’);但是操作的次数有上限m,问在有限的操作数范围内,能够得到最大连续的相同字符的子串的长度是多少。
输入描述:
第一行两个整数 n , m (1<=m<=n<=50000),第二行为长度为n且只包含’a’和’b’的字符串s。
输出描述:
输出在操作次数不超过 m 的情况下,能够得到的 最大连续 全’a’子串或全’b’子串的长度。
示例1
输入:
8 1
aabaabaa
复制
输出:
5
复制
说明:
把第一个 ‘b’ 或者第二个 ‘b’ 置成 ‘a’,可得到长度为 5 的全 ‘a’ 子串。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
 
public class Main {
 
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int len = sc.nextInt();
        int oper = sc.nextInt();
        String str = sc.next();
        System.out.println(windowSolve(str, oper, len));
 
    }
    private static int windowSolve(String str, int oper, int len) {
        int res=Integer.MIN_VALUE; 
        int left=0, right=0;  // 滑动窗口设置两个指针lr
        int an=0, bn=0;   //用来计数窗口中a/b的个数
 
        while(right<len){
            if(str.charAt(right)=='a') {
                an++;
            }else {
                bn++;
            }
            // right一直往右走,寻找可行解
            if(an<=oper||bn<=oper){ 
                right++;
 
            }else{  // 从可行解中找最优解:left开始往右走
                // 此时窗口中已经出现了oper个可以改变的字符,更新结果
                res = Math.max(res, right-left);
 
                // left指针往左走,窗口中退出一个字符相应的计数减1,
                // 而right指针新指的字符计数已经在刚进入while语句时的if判断已加1
                if(str.charAt(left)=='a'){ 
                    left++;
                    an--;
                }else{
                    left++;
                    bn--;
                }
                right++;
            }
        }
 
        res = Math.max(res, right-left);
        return res;
    }
}

4.以下函数用于将一颗二叉搜索树转换成一个有序的双向链表。要求不能创建任何新的节点,只能调整树种节点指针的指向。

如输入下图中左边的二叉搜索树,则输出转换后的排序双向链表:

  10

/      \

6 14

/ \ / \

4 8 12 16

转换成:

4 <=> 6 <=> 8 <=> 10 <=> 12 <=> 14 <=> 16

请指出程序代码中错误的地方(问题不止一处,请尽量找出所有你认为错误的地方):

1 #include

2 using namespace std;

3

4 struct TreeNode {

5 int val;

6 TreeNode *left, *right;

7 };

8

9 TreeNode* Convert(TreeNode* root){

10 if (root == NULL)

11 return root;

12

13 TreeNode* listHead = NULL;

14 TreeNode* listLastNode = NULL;

15

16 stack<TreeNode*> s;

17 while(root){

18 while(root){

19 root=root->left;

20 s.push(root);

21 }

22 root=s.top();

23 s.pop();

24 if (listHead == NULL){

25 listHead = root;

26 }else{

27 listLastNode->right = root;

28 }

29 listLastNode = root;

30 root= root->right;

31 }

32 return listHead;

33 }

你的答案
请指出程序代码中错误的地方(问题不止一处,请尽量找出所有你认为错误的地方):

1 #include

2 using namespace std;

3

4 struct TreeNode {

5 int val;

6 TreeNode *left, *right;

7 };

8

9 TreeNode* Convert(TreeNode* root){

10 if (root == NULL)

11 return root;

12

13 TreeNode* listHead = NULL;

14 TreeNode* listLastNode = NULL;

15

16 stack<TreeNode*> s;

17 while(root){

18 while(root){
s.push(root);
19 root=root->left;

20

21 }

22 root=s.top();

23 s.pop();

24 if (listHead == NULL){

25 listHead = root;

26 }else{

27 listLastNode->right = root;

28 }

29 listLastNode = root;

30 root= root->right;

31 }

32 return listHead;

33 }

TreeNode* Convert(TreeNode* root)
{
    if (root == NULL)
        return root;
    TreeNode* listHead = NULL;
    TreeNode* listLastNode = NULL;
    stack<TreeNode*> s;
    while(root||!s.empty())//
    {
        while(root!=NULL)
        {
            s.push(root);//
            root=root->left;
        }
        root=s.top();
        s.pop();
        if (listHead == NULL)
        {
            listHead = root;
        }
        else
        {
            listLastNode->right = root;
            root->left=listLastNode;
        }
        listLastNode = root;
        root= root->right;
    }
    return listHead;

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值