【问题标题】:minimum operations required to make the longest character interval equal to K使最长字符间隔等于 K 所需的最少操作
【发布时间】:2018-10-10 21:03:41
【问题描述】:

我在一次比赛中被问到这个问题。 给定一个仅包含 M 和 L 的字符串,我们可以将任何“M”更改为“L”或将任何“L”更改为“M”。此函数的目标是计算为达到所需的最长 M 间隔长度 K,我们必须进行的最少更改次数。
例如,给定 S = "MLMMMLM" 和 K = 3,函数应该返回 1。我们可以改变位置 4 的字母(从 0 开始计数)得到 "MLMMMLM",其中字母 "M" 的最长间隔是正好三个字符长。

再举个例子,给定 S = "MLMMMLMMMM" 和 K = 2,函数应该返回 2。例如,我们可以修改位置 2 和 7 的字母,得到字符串 "MLLMMLMLMM",它满足期望属性。

这是我到目前为止所尝试的,但我没有得到正确的输出: 我正在遍历字符串,只要最长的字符数超过 K,我就用 L 替换 M。

public static int solution(String S, int K) {

    StringBuilder Str = new StringBuilder(S);

    int longest=0;int minCount=0;
    for(int i=0;i<Str.length();i++){
        char curr=S.charAt(i);
        if(curr=='M'){
            longest=longest+1;
        if(longest>K){
           Str.setCharAt(i, 'L');
           minCount=minCount+1;
           }
        }

        if(curr=='L')
         longest=0;
 }
  if(longest < K){
        longest=0;int indexoflongest=0;minCount=0;
        for(int i=0;i<Str.length();i++){
            char curr=S.charAt(i);
            if(curr=='M'){
            longest=longest+1;
            indexoflongest=i;

            }
            if(curr=='L')
              longest=0;

        }
        Str.setCharAt(indexoflongest, 'M');
        minCount=minCount+1;



    }
  return minCount;
}

【问题讨论】:

  • 你是如何处理其他案件的?不能有需要用M替换L的情况吗?代码在哪里?
  • 我已编辑代码以包含该条件。但它不是最佳的。
  • 最优是什么意思?期望的运行时复杂度是多少?是不是给出了错误的答案?
  • 显然应该有人在 ML 中添加解决方案 :)
  • @GaganDeep:你想在这次编程比赛中作弊吗? app.codility.com/programmers/custom_challenge/… - 减少复杂性 - Codility 和 ASML?

标签: java c# algorithm data-structures dynamic-programming


【解决方案1】:

这个算法有两个部分,因为我们想要获得等于 K 的最长字符间隔。

  1. 我们已经有了一个 >= K 的区间,所以现在我们需要适当地更改一些字符,因此我们贪婪地更改每 (k + 1) 个字符,然后再次从 0 开始计数。

  2. 现在,如果间隔小于 K,我将需要在数组上运行一个滑动窗口。在运行这个窗口时,我基本上考虑在这个长度为 K 的窗口中将所有 L 转换为 M。但这会带来增加间隔长度的副作用,因为外部可能有 K,所以这个变量 (int nec) 跟踪那。所以现在我还必须考虑将(K 长度)窗口外的 2 个可能的 M 转换为 L。

这是 C++ 中完整的可运行代码。祝你有美好的一天。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector <int> vi;
typedef pair<int, int> ii;



int change(string s, int k) {
    // handling interval >= k
    bool flag = false;
    int ans = 0;
    int cnt = 0;
    for(int i=0; i<s.size(); i++) {
        if(s[i] == 'M') cnt++;
        else cnt = 0;
        if(cnt == k) flag = true;
        if(cnt > k) s[i] = 'L', ans++, cnt = 0;
    }
    if(flag) return ans;

    // handling max interval < k
    // If the interval is too big.
    if(k > s.size()) {
        cerr << "Can't do it.\n"; exit(0);
    }

    // Sliding window
    cnt = 0;
    for(int i=0; i<k; i++) {
        if(s[i] == 'L') cnt++;
    }
    ans = cnt + (s[k] == 'M'); // new edit
    int nec = 0; // new edit
    for(int i=k; i<s.size(); i++) {
        if(s[i-k] == 'L') cnt--;
        if(s[i] == 'L') cnt++;
        nec = 0;
        if(i-k != 0 && s[i-k-1] == 'M')
            nec++;
        if(i < s.size()-1 && s[i+1] == 'M')
            nec++;
        ans = min(ans, cnt + nec);
    }

    return ans;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);

    string s;
    int k;

    cin >> s >> k;

    int ans = change(s, k);
    cout << ans << "\n";

    return 0;
}

【讨论】:

  • 谢谢,但它给出了错误的答案。 for, change("MLMMMLMMMM", 2), 它返回 3 但答案应该是 2. for, change("MLMMLLM", 3), 它返回 3 但答案应该是 1。
  • 我做了一些改变。你现在能确认它是否正确吗?
  • 嗯,在这种情况下可能是错误的?:change('MLMM', 3);得到 1 但预期 2。
  • 是的!谢谢你的案子。新变化。
  • 我认为你应该为你的答案添加一些解释。尽管您的解决方案符合比赛的期望。
【解决方案2】:
 int
process_data(const char *m, int k)
{
    int m_cnt = 0, c_cnt = 0;
    char ch;
    const char *st = m;
    int inc_cnt = -1;
    int dec_cnt = -1;

    while((ch = *m++) != 0) {
        if (m_cnt++ < k) {
            c_cnt += ch == 'M' ? 0 : 1;
            if ((m_cnt == k) && (
                    (inc_cnt == -1) || (inc_cnt > c_cnt))) {
                inc_cnt = c_cnt;
            }
        }
        else if (ch == 'M') {
            if (*st++ == 'M') {
                /*
                 * losing & gaining M carries no change provided
                 * there is atleast one L in the chunk. (c_cnt != 0)
                 * Else it implies stretch of Ms
                 */
                if (c_cnt <= 0) {
                    int t;

                    c_cnt--;

                    /*
                     * compute min inserts needed to brak the
                     * stretch to meet max of k.
                     */
                    t = (k - c_cnt) / (k+1);
                    dec_cnt += t;
                }
            }
            else {
                ASSERT(c_cnt > 0, "expect c_cnt(%d) > 0", c_cnt);
                ASSERT(inc_cnt != -1, "expect inc_cnt(%d) != -1", inc_cnt);
                /* Losing L and gaining M */
                if (--c_cnt < inc_cnt) {
                    inc_cnt = c_cnt;
                }
            }
        }
        else {
            if (c_cnt <= 0) {
                /*
                 * take this as a first break and restart
                 * as any further addition of M should not
                 * happen. Ignore this L
                 */
                st = m;
                c_cnt = 0;
                m_cnt = 0;
            }
            else if (*st++ == 'M') {
                /* losing m & gaining l */
                c_cnt++;
            }
            else {
                // losing & gaining L; no change
            }
        }
    }
    return dec_cnt != -1 ? dec_cnt : inc_cnt;
}

【讨论】:

  • 步行一次。当你走路时,得到改变的计数,以满足拉伸中至少 K 个 Ms 计数,并取最小的作为 inc_cnt,在同一次步行中,递减 c_cnt,当 Ms 的拉伸越过 K 并且每次拉伸时,c_cnt 将变为负数找到所需的插入数量并总结。
  • 我有一个错误。我应该只在伸展结束时数 t,
【解决方案3】:

更正的代码:

int
process_data(const char *m, int k)
{
    int m_cnt = 0, c_cnt = 0;
    char ch;
    const char *st = m;
    int inc_cnt = -1;
    int dec_cnt = -1;

    while((ch = *m++) != 0) {
        if (m_cnt++ < k) {
            c_cnt += ch == 'M' ? 0 : 1;
            if ((m_cnt == k) && (
                    (inc_cnt == -1) || (inc_cnt > c_cnt))) {
                inc_cnt = c_cnt;
            }
        }
        else if (ch == 'M') {
            if (*st++ == 'M') {
                /*
                 * losing & gaining M carries no change provided
                 * there is atleast one L in the chunk. (c_cnt != 0)
                 * Else it implies stretch of Ms
                 */
                if (c_cnt <= 0) {
                    c_cnt--;
                }
            }
            else {
                ASSERT(c_cnt > 0, "expect c_cnt(%d) > 0", c_cnt);
                ASSERT(inc_cnt != -1, "expect inc_cnt(%d) != -1", inc_cnt);
                /* Losing L and gaining M */
                if (--c_cnt < inc_cnt) {
                    inc_cnt = c_cnt;
                }
            }
        }
        else {
            if (c_cnt <= 0) {

                /*
                 * compute min inserts needed to brak the
                 * stretch to meet max of k.
                 */
                dec_cnt += (dec_cnt == -1 ? 1 : 0) + ((k - c_cnt) / (k+1));

                /*
                 * take this as a first break and restart
                 * as any further addition of M should not
                 * happen. Ignore this L
                 */
                st = m;
                c_cnt = 0;
                m_cnt = 0;
            }
            else if (*st++ == 'M') {
                /* losing m & gaining l */
                c_cnt++;
            }
            else {
                // losing & gaining L; no change
            }   
        }
    }
    if (c_cnt <= 0) {

        /*
         * compute min inserts needed to brak the
         * stretch to meet max of k.
         */
        dec_cnt += (dec_cnt == -1 ? 1 : 0) + ((k - c_cnt) / (k+1));
    }

    return dec_cnt != -1 ? dec_cnt : inc_cnt;
}

【讨论】:

    猜你喜欢
    • 2020-02-12
    • 1970-01-01
    • 2017-03-16
    • 2019-08-14
    • 1970-01-01
    • 2021-09-08
    • 2012-11-08
    • 2023-03-20
    相关资源
    最近更新 更多