数据结构 _ PAT练习 _ 7-13 Insert or Merge

原题

点此链接1

解题思路

参考课本:高等教育出版社 - 陈越主编 - 《数据结构》
参考视频:MOOC - 浙江大学 - 《数据结构与算法》

  本题主要考察的是简单插入排序(课本P268)以及归并排序的非递归算法(MOOC 9.4)。两种算法前者较易理解,后者的非递归算法相对更难。

  本题的切入点:

  1. 根据输入数据串判断是插入排序还是归并排序
  2. 确定插入排序当前的位置
  3. 确定归并排序当前子串的长度

  判断是何排序算法,只需比较两种算法子串的不同即可:

  1. 插入排序得到的子列必然是一个有序序列 + 剩余原序列
  2. 归并排序得到的子列必然是一个有序序列 + 无序序列(与原序列不同)

  题目中已明确不存在歧义,故而无需考虑其他特殊情况

  如果是插入排序,则当前插入位置就是 “有序序列” 的末尾,后续就只需要新增一个插入数据作 “简单插入算法” 并输出结果。

  如果是归并排序,则较为繁琐。从这几个角度入手:

  1. 子序列的长度不会大于目前的有序序列的长度
  2. 子序列的长度必然是2的幂次
  3. 每一个子序列都是有序的(注意尾列的长度不一,需要单独处理)

代码

/**
 * @file Insert_or_Merge.cpp
 * @author your name (you@domain.com)
 * @brief https://pintia.cn/problem-sets/16/problems/675
 * @version 0.1
 * @date 2021-02-20
 * 
 * @copyright Copyright (c) 2021
 * 
 */

/*
 *
 * 解题思路
 * 判别是归并还是插入
 *      读入有序序列
 *      后面与原始序列有一个不一样那就是归并排序
 *      后面与原始序列完全一样就是插入排序
 * 
 * 如果是插入排序
 *      读入下一个数据作插入排序算法
 * 
 * 如果是归并排序
 *      确定子串的长度
 *          是不是2的幂次,取一个不大于目前有序序列长度的最大的2的幂次数
 *          需要简单判断一下现在是不是每一个子串都符合要求,不然就作除2处理再判断
 *      作下一次归并运算
 */

#include <iostream>
#include <vector>

using namespace std;

void Merge(vector<int>::iterator beg, vector<int>::iterator lefS,
           vector<int>::iterator rigS, const vector<int>::iterator &rigE)
{
    auto size = rigE - lefS;
    const auto lefE = rigS; // 尾后迭代器!
    while (lefS != lefE && rigS != rigE)
    {
        if (*lefS < *rigS)
            *(beg++) = *(lefS++);
        else
            *(beg++) = *(rigS++);
    }

    while (lefS != lefE)
        *(beg++) = *(lefS++);
    while (rigS != rigE)
        *(beg++) = *(rigS++);

    lefS = rigE - size;
    beg = beg - size;
    for (auto i = 0; i < size; i++)
        *(lefS++) = *(beg++);
}

int main()
{
    int n;
    cin >> n;
    vector<int> d1;
    vector<int> d2;

    for (auto i = 0; i < n; i++)
    {
        int tmp;
        cin >> tmp;
        d1.push_back(tmp);
    }

    auto res = 0; // 0 -> insertion; 1 -> merge
    auto len = 0;
    {
        auto flag = true;
        auto detectFlag = false;
        for (auto i = 0; i < n; i++)
        {
            int tmp;
            cin >> tmp;

            // 目前还是有序的序列
            if (flag)
            {
                // 发现无序因子
                if (!d2.empty() && tmp < d2.back())
                {
                    flag = false;
                    len = i;
                }
            }
            // 目前已经是无序的因子
            else
            {
                // 发现后续因子与原序列不同,则为归并排序
                if (!detectFlag && tmp != d1[i])
                {
                    detectFlag = true;
                    res = 1;
                }
            }
            d2.push_back(tmp);
        }
    }

    if (res)
    {
        const auto size = static_cast<int>(d2.size());
        cout << "Merge Sort" << endl;
        // 选择靠近i的2的次方数
        for (auto i = 1;; i *= 2)
            if (i >= len)
            {
                len = i;
                break;
            }
        // 检测片段长度
        auto Judge = [&d2, &len, size]() -> bool {
            auto iter = d2.begin();
            for (; iter < (d2.end() - len); iter += len)
                for (auto i = 1; i < len; ++i)
                    if (*(iter + i - 1) > *(iter + i))
                        return false;
            for (; iter != (d2.end() - 1); ++iter)
                if (*iter > *(iter + 1))
                    return false;
            return true;
        };
        if (len != 1)
            while (!Judge())
                len /= 2;
        auto offset = 0;
        for (; offset < (size - 2 * len); offset += (2 * len))
            Merge(d1.begin() + offset, d2.begin() + offset, d2.begin() + offset + len, d2.begin() + offset + 2 * len);
        // 尾部处理
        if (offset + len < size)
            Merge(d1.begin() + offset, d2.begin() + offset, d2.begin() + offset + len, d2.end());
    }
    else
    {
        cout << "Insertion Sort" << endl;
        const auto tmp = d2[len];
        auto iter = d2.begin() + len;
        for (; iter != d2.begin() && *(iter - 1) > tmp; --iter)
            *iter = *(iter - 1);
        *iter = tmp;
    }

    // out the data
    {
        auto iter = d2.begin();
        for (; iter != d2.end() - 1; ++iter)
            cout << *iter << " ";
        cout << *iter << endl;
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 MyBatis 中,可以使用 `<insert>` 标签来处理插入操作,使用 `<update>` 标签来处理更新操作。但是,如果你想实现一个插入或更新操作,你需要写两个不同的 SQL 语句,这很麻烦。幸运的是,Oracle 提供了一个 MERGE 语句,可以同时实现插入和更新操作。 下面是一个基本的 Oracle MERGE 语句示例: ```sql MERGE INTO table_name t USING (SELECT ? col1, ? col2, ? col3 FROM dual) s ON (t.key_column = ?) WHEN MATCHED THEN UPDATE SET t.col1 = s.col1, t.col2 = s.col2, t.col3 = s.col3 WHEN NOT MATCHED THEN INSERT (t.key_column, t.col1, t.col2, t.col3) VALUES (?, ?, ?, ?) ``` 其中,`table_name` 是要插入或更新的表名;`key_column` 是用于匹配的列名;`col1`、`col2`、`col3` 是要插入或更新的列名;`?` 是占位符,用于传递参数。 在 MyBatis 中,你可以使用 `<update>` 和 `<insert>` 标签来执行这个 MERGE 语句。下面是一个示例: ```xml <update id="insertOrUpdate" parameterType="com.example.entity.MyEntity"> MERGE INTO my_table t USING (SELECT #{col1} col1, #{col2} col2, #{col3} col3 FROM dual) s ON (t.id = #{id}) WHEN MATCHED THEN UPDATE SET t.col1 = s.col1, t.col2 = s.col2, t.col3 = s.col3 WHEN NOT MATCHED THEN INSERT (t.id, t.col1, t.col2, t.col3) VALUES (#{id}, #{col1}, #{col2}, #{col3}) </update> ``` 在这个示例中,`MyEntity` 是一个 Java 实体类,包含 `id`、`col1`、`col2`、`col3` 四个属性。`parameterType` 属性指定了传递给 SQL 语句的参数类型。在 SQL 语句中,使用 `#{}` 占位符来引用 Java 实体类中的属性。 当你调用这个 SQL 语句时,如果 `id` 已经存在于表中,则会更新 `col1`、`col2`、`col3` 列的值;否则,会插入新的一行,其中包括 `id`、`col1`、`col2`、`col3` 列的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值