求最小交换次数(未解决)

暂时保存代码,求最长子串代码正确

#include <iostream>
#include <string>

using namespace std;

/* n个人随机围成圈,最终想让男生坐一起,女生坐一起,
 * 每次可以命令两个人交换位置,求最小交换次数。
 * 样例:
 * 输入:3,FMF;输出:0。
 * 输入:4,FMFM;输出:1。
 * */
int solution(int n, string s) {
    /*求出最长子串*/
    int p = 0, q = 1, cnt = 0;
    // 找到s[p] != s[q]的地方,再将p++,q++作为遍历起点
    while (q < n)
    {
        if (s[p] == s[q])
        {
            p++; q++;
        }
        else
            break;
    }
    // m_p:最长子串的左端,m_q:最长子串的右端再右移一位
    int pos = q, maxSize = 0, m_p, m_q;
    p++; q++;

    // 遍历一圈,找到最长子串
    // 循环结束,p、q会落在连续相同子串的后面一位和两位
    /*例如:
     * "FMMMFMMMMMF",起始p = 1,q = 2,最终p = 1,q = 2,pos = 2
     * 因为循环中最后一个连续相同子串是“FF”,即数组头尾所组成的,
     * p、q会落在“FF”的后面一位和两位,即p = 1,q = 2
     *
     * "FMMMFMMMMMM",起始p = 1,q = 2,最终p = 0,q = 1,pos = 1
     * 循环中最后一个连续相同子串是“MMMMMM”,
     * p、q会落在“MMMMMM”的后面一位和两位,即p = 0,q = 1
     * */
    bool flag = true;
    if (s[0] == s[n - 1]) pos++;  // 根据首尾元素调整pos位置
    while (flag)
    {
        if (s[p] == s[q])
        {
            q++;
            if (q == n)  // 将q跳回数组头
                q = q % n;
        }
        else
        {
            if (p < q)
            {
                if (maxSize < q - p)
                {
                    maxSize = q - p;
                    m_p = p;
                    m_q = q;
                }
            }
            else
            {
                if (maxSize < q + n - p)
                {
                    maxSize = q + n - p;
                    m_p = p;
                    m_q = q;
                }
            }
            p = q;
            q++;
            if (q == n)  // 将q跳回数组头
                q = q % n;
        }
        if (q == pos) flag = !flag;
    }

    // 打印最长子串
    if (m_q > m_p)
    {
        cout << "最长子串:";
        for (int i = m_p; i < m_q; ++i)
            cout << s[i];
        cout << endl;
        cout << "子串左端下标:" << m_p << endl
             << "子串右端下标后一位:" << m_q << endl;
    }
    else
    {
        cout << "最长子串:";
        for (int i = m_p; i < n; ++i)
            cout << s[i];

        for (int i = 0; i < m_q; ++i)
            cout << s[i];
        cout << endl;
        cout << "子串左端下标:" << m_p << endl
             << "子串右端下标后一位:" << m_q << endl;
    }

    /*将其余位置与子串相同元素搬到子串旁边*/
    int j;
    char temp;

    if (m_q < m_p)
    {
        j = m_q;

        for (int i = m_q + 1; i < m_p; ++i)
        {
            // 找s[i]与子串元素相同元素
            if (s[i] != s[m_p]) continue;
            // 找s[j]与子串元素不同元素
            while (s[j] == s[m_p]) j++;
            // 交换
            temp = s[i];
            s[i] = s[j];
            s[j] = temp;
            cnt++;
        }
    }
    else
    {
        // 交换子串前的字符
        if (m_p >= 2)
        {
            j = m_p - 1;
            for (int i = m_p - 2; i >= 0; --i)
            {
                if (s[i] != s[m_p]) continue;
                while (s[j] == s[m_p]) j--;
                // 交换
                temp = s[i];
                s[i] = s[j];
                s[j] = temp;
                cnt++;
            }
        }
        // 交换子串后的字符
        if (n - m_q >= 2)
        {
            j = m_q;
            for (int i = m_q + 1; i < n; ++i)
            {
                if (s[i] != s[m_p]) continue;
                while (s[j] == s[m_p]) j++;
                // 交换
                temp = s[i];
                s[i] = s[j];
                s[j] = temp;
                cnt++;
            }
        }
    }
    return cnt;
}

int main()
{
    string s = "FMMMMMMMFMMMM";
    int n = s.size();
    cout << "原始字符串:" << s << endl;
    int cnt = solution(n, s);
    cout << "交换次数:" << cnt << endl;

    return 0;
}
posted @   修凡  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示