zoukankan      html  css  js  c++  java
  • 【2018今日头条笔试题】字符交换

    题目

    链接:https://www.nowcoder.com/question/next?pid=8537228&qid=141031&tid=22230511

    **Level: ** 2018算法工程师笔试题

    Discription:
    字符串S由小写字母构成,长度为n。定义一种操作,每次都可以挑选字符串中任意的两个相邻字母进行交换。询问在至多交换m次之后,字符串中最多有多少个连续的位置上的字母相同?

    第一行为一个字符串S与一个非负整数m。(1 <= |S| <= 1000, 1 <= m <= 1000000)
    一个非负整数,表示操作之后,连续最长的相同字母数量。

    Example 1:

    Input: abcbaa 2
    Output: 2
    

    Note:

    • 使2个字母a连续出现,至少需要3次操作。即把第1个位置上的a移动到第4个位置。
      所以在至多操作2次的情况下,最多只能使2个b或2个a连续出现。

    代码

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<algorithm>
    
    using namespace std;
    
    vector<vector<int>> loc(26); //二维数组初始化
    int mem[1001][1001];
    int dp(int start, int end, vector<int> loc)
    {
        if (start == end || start == (end + 1) || start > end)
        {
            mem[start][end] = 0;
            return 0;
        }
        else if (mem[start][end] != -1)
            return mem[start][end];
        else
        {
            mem[start][end] = dp(start + 1, end - 1, loc) + loc[end] - loc[start] - (end - start);
            return mem[start][end];
        }
    }
    
    int main()
    {
        string str;
        int m;
        cin >> str >> m;
        for (int i = 0; i < str.length(); i++)
            loc[str[i] - 'a'].push_back(i);
    
        int nums[26] = { 0 };
    
        for (int i = 0; i < 26; i++)
        {
            fill(mem[0], mem[0] + 1001 * 1001, -1);
            if (loc[i].size() >= 1)
                nums[i] = 1;//至少有一个连续的
            for (int j = 0; j < loc[i].size(); j++)
            {
                for (int k = j + 1; k < loc[i].size(); k++)
                {
                    int len = k - j + 1;
                    int lx = dp(j, k, loc[i]);
                    if (lx <= m && len > nums[i])
                        nums[i] = len;
                }
            }
        }
        sort(nums, nums + 26);
        cout << nums[25] << endl;
        system("pause");
        return 0;
    }
    

    思考

    • 算法时间复杂度为O((S^3)),空间复杂度为O((S^2) ),S是字符串的长度,递归最深是S/2。
    • DP实现,转移方程是dp(start, end, loc) = dp(start + 1, end - 1, loc) + loc[end] - loc[start] - (end - start);最优的操作总是两边向中间聚合。DP的难点在于想通如何把大问题化解成为小问题,其次是想明白小问题的最优操作是怎样的,比如这题中的两边向中间聚合,如果这一步想不通,即使化解成为小问题也求解不出来。
    • 光用递归实现会超时,定义一个数组来存放中间重复计算的值。
  • 相关阅读:
    OpenStack 对接 Ceph
    《Netty权威指南》(二)NIO 入门
    《Netty权威指南》(一)走进 Java NIO
    进程间通信 IPC(Inter-Process Communication)
    CentOS7 下安装 iSCSI Target(tgt) ,使用 Ceph rbd
    CentOS7 下编译安装 Samba,什么是 SMB/CIFS 协议
    《Netty权威指南》目录
    CentOS7 下安装 NFS,Linux/Windows 作为客户端
    数据结构汇总
    Ceph 块设备
  • 原文地址:https://www.cnblogs.com/zuotongbin/p/10543865.html
Copyright © 2011-2022 走看看