南大算法设计与分析课程OJ答案(2)

问题 A: 最大子序列和问题

时间限制: 1 Sec  内存限制: 4 MB
提交: 184  解决: 66
提交 状态 算法问答

题目描述

给定一整数序列 a1, a2, …, an,求 a1~an 的一个子序列 ai~aj,使得从 ai 到 aj 的和最大。

只需要求出最大子序列的和,而不需要求出最大的那个序列。

输入

一组整数,数字和数字之间以空格隔开。

输出

该整数序列中最大子序列的和

样例输入

-2 11 -4 13 -5 -2

样例输出

20

提示

应用穷举法可以得到 O(n3) 的算法,优化它即可得到 O(n2) 的算法。这两个算法将会超时。

利用分治的思想可以有 O(n*logn) 的算法。

也有聪明的算法,它的复杂度是 O(n) 的。

另请注意:输入多少个数是未知的。请思考如何处理。

答案看这里

http://www.cnblogs.com/likaiming/p/8570205.html

问题 B: 所有的逆序对

时间限制: 2 Sec  内存限制: 5 MB
提交: 289  解决: 49
提交 状态 算法问答

题目描述

给出一个字符串数组,如果(按照字典序)一个大的字符串在比它小的字符串前面我们称这两个字符串组成一个“逆序对”。你需要找到所有的逆序对的个数。

输入

第一行是数组大小,第二行是以空格分隔的字符串数组.

注:预先知道每个字符串的长度都是 10.

输出

所有的逆序对个数. 这次需要大家先输出一个字符串,它是“我已阅读关于抄袭的说明”的汉语拼音.输出此行的提交我们将认为已经完全阅读并了解了“关于抄袭的说明”公告.

注意:结果比较大,请用 long 类型保存.

样例输入

3
aaaaaaaaaa cccccccccc bbbbbbbbbb

样例输出

wo yi yue du guan yu chao xi de shuo ming
1

提示

不要使用蛮力算法

答案

暴力解法,会超时

long long a(vector<string>& v, int pos1, int pos2) {
    long long w = 0;
    for (int i = pos1; i <= pos2; ++i) {
        for (int j = i + 1; j <= pos2; ++j) {
            if (v[i] > v[j])
                ++w;
        }
    }
    return w;
}

bf

归并排序的思想,只需要在归并排序的基础之上加上一个统计量,和一行代码,但是下面的做法会超出内存限制

void merge(vector<string>& v, int pos1, int mid, int pos2, long long& nums) {
    //从0开始的数组,如果两个位置分别为p1和p2,其中p1<p2,则p1到p2距离的元素有p2-p1+1个
    vector<string> n1 (v.begin()+pos1,v.begin()+mid+1);
    vector<string> n2 (v.begin()+mid+1,v.begin()+pos2+1);
    n1.emplace_back("zzzzzzzzzzzzzzzzzzzz");
    n2.emplace_back("zzzzzzzzzzzzzzzzzzzz");
    int n1_pos = 0;
    int n2_pos = 0;
    for (int i = pos1; i <= pos2;++i) {
        if (n1[n1_pos] <= n2[n2_pos]) {
            v[i] = n1[n1_pos];
            ++n1_pos;
        }else{
            //在这加上统计量
            nums += n1.size() - n1_pos-1;
            v[i] = n2[n2_pos];
            ++n2_pos;
        }
    }
}
void mergesort(vector<string>& v, int pos1, int pos2, long long& nums) {
    if (pos1 < pos2) {
        int mid = (pos1 + pos2) / 2;
        mergesort(v,pos1,mid,nums);
        mergesort(v,mid+1,pos2,nums);
        merge(v,pos1,mid,pos2,nums);
    }
}

//这是测试用例
int main()
{
    int nums = 0;
    cin >> nums;
    string temp;
    vector<string> v(nums,"");
    for (int i = 0; i < nums; ++i) {
        cin >> temp;
        v[i] = temp;
    }
    vector<string> v = { "aaaaaaaaaa", "cccccccccc", "bbbbbbbbbb" };
    long long result = 0;
    mergesort(v, 0, v.size() - 1, result);

    cout << "wo yi yue du guan yu chao xi de shuo ming" << endl;
    cout << result << endl;

    //system("pause");
    return 0;
}

归并解法

经大佬提醒,不在递归时分配vector,而是在开始递归之前申请一个help的vector用来帮助归并排序,这样可以减小内存使用,但是上面使用哨兵的方法就不能用了,代码稍微复杂了一些,但任然是归并排序加上一行统计代码。

void merge(vector<string>& v, int pos1, int mid, int pos2, long long& nums, vector<string>& help) {
    //从0开始的数组,如果两个位置分别为p1和p2,其中p1<p2,则p1到p2距离的元素有p2-p1+1个
    for (int i = pos1; i <= pos2; ++i)
        help[i] = v[i];
    int n1_pos = pos1;
    int n2_pos = mid+1;
    for (int i = pos1; i <= pos2;++i) {
        //当一个数组已经遍历完成时
        if (n1_pos == mid + 1) {
            while (n2_pos != pos2 + 1) {
                v[i++] = help[n2_pos++];
            }
            break;
        }
        if (n2_pos == pos2 + 1) {
            while (n1_pos != mid + 1) {
                v[i++] = help[n1_pos++];
            }
            break;
        }
        //其他情况
        if (help[n1_pos] <= help[n2_pos]) {
            v[i] = help[n1_pos];
            ++n1_pos;
        }else{
            //在这加上统计量
            nums += mid-n1_pos+1;
            v[i] = help[n2_pos];
            ++n2_pos;
        }
    }
}
void mergesort(vector<string>& v, int pos1, int pos2, long long& nums,vector<string>& help) {
    if (pos1 < pos2) {
        int mid = (pos1 + pos2) / 2;
        mergesort(v,pos1,mid,nums,help);
        mergesort(v,mid+1,pos2,nums,help);
        merge(v,pos1,mid,pos2,nums,help);
    }
}

//这是测试用例
int main()
{
    int nums = 0;
    cin >> nums;
    string temp;
    vector<string> v(nums,"");
    for (int i = 0; i < nums; ++i) {
        cin >> temp;
        v[i] = temp;
    }
    //vector<string> v = { "4","3","2","1" };
    vector<string> help(v.size()," ");
    long long result = 0;
    mergesort(v, 0, v.size() - 1, result,help);

    cout << "wo yi yue du guan yu chao xi de shuo ming" << endl;
    cout << result << endl;

    system("pause");
    return 0;
}

归并排序内存优化

原文地址:https://www.cnblogs.com/likaiming/p/8634491.html

时间: 2024-10-13 04:06:20

南大算法设计与分析课程OJ答案(2)的相关文章

南大算法设计与分析课程OJ答案(3)

问题 A: 动态中位数问题 时间限制: 1 Sec  内存限制: 8 MB提交: 866  解决: 102提交 状态 算法问答 题目描述 输入一组整数a1, a2, -, an ,每输入一个整数,输出到此时为止的中位数. 中位数定义:如果数串的大小是偶数 2j,中位数是从小到大排列的第 j 个数:如果数串的大小是奇数 2j+1,中位数是从小到大排列的第 j+1 个数. 输入 一组整数,数字和数字之间以空格隔开. 输出 一组整数,数字和数字之间以空格隔开.最后一个数后面也有空格. 第 i 个输出的

南大算法设计与分析课程复习笔记(2)

一.几种比较复杂度的符号 数据结构有描述,相关严格数学定义也不想说了,就这么过了吧. 二.最大子数组的几种解决方法 从最复杂的暴力解法过渡到最简单的动态规划 解析和代码见这里:http://www.cnblogs.com/likaiming/p/8570205.html 三.作业调度问题 后面的动态规划和贪婪算法都会给出解答,这里不多说 四.矩阵链乘法 解析和代码见这里:http://www.cnblogs.com/likaiming/p/8053094.html 原文地址:https://ww

南大算法设计与分析课程复习笔记(3)L3 - Recursion

一.递归方程 按照分治的思想,可以将一个递归的复杂度写成递归方程 一.解递归方程--猜然后证明 该方法又称为代入法,步骤如下: 1.猜解的形式 2.数学归纳法证明正确 例子: 我们假设有如下递归式: 我们猜其解为T(n)=O(nlgn),然后对递归式进行替换,得 特别注意:我们替换之后得出的结果必须严格符合猜想,上面的例子如果最后得出T(n)<=cnlgn+1,都说明我们猜错了,需要选择新的猜解式. 二.解递归方程--递归树解 感觉这种方法比较的麻烦,一般用代入法和下面的master定理来做 例

算法设计与分析课程复习笔记(1)

一.计算模型 1.1 定义: 我们在思考和处理算法的时候是机器无关.实现语言无关的.所有的算法运行在一种"抽象的机器"之上,这就是计算模型. 1.2 种类 图灵机是最有名的计算模型,本课使用更简单更合适的RAM计算模型. 1.3 RAM(Random Access Machine)模型 RAM模型的基本构成如下: RAM计算模型有如下特点: 一个简单操作花费一步:键值比较.加减.内存访问 没有操作可以被分解:循环.子程序 内存:访存是一个简单操作.无限制的内存 二.算法设计 2.1 算

《计算机算法设计与分析》v4 第1章 算法概述 算法实现题答案

博主今年刚上大三,正好开算法这门课.由于博主本人比较喜欢算法但又比较懒,啃不动算法导论,所以决定拿这本书下手. 这本书是王晓东的第四版<计算机算法设计与分析>.初步打算将每章后面的算法题都用代码实现. 有些题跟某个ACM题目很像,我会把该ACM题的链接贴上.有的题没OJ交所以可能是错的.如有发现,还望指出. 1-1 统计数字问题 http://poj.org/problem?id=2282 这个题要按位分解,一位一位的来处理. #include<iostream> #include

(转)常用的算法设计与分析-一夜星辰的博客

算法设计与分析 分治法 思想 1. 将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同.递归地解这些子问题,然后将各子问题的解合并得到原问题的解. 2. divide-and-conquer(P) { if(|P| <= n0)adhoc(P); divide P into samller subinstances P1,P2...,Pk; for(int i = 1;i < k;i++) { yi = divide-and-conquer(Pi); } retu

大屏设计系列之五——大屏设计语言分析

如果您想订阅本博客内容,每天自动发到您的邮箱中,请点这里 作者:蓝蓝 蓝蓝设计经常会接到大屏设计的项目,比如中国移动互联网监控大屏可视化设计及开发.太极集团承接的中央台应急指挥中心大屏可视化设计.交大思源承接的北京地铁轨道批挥中心大屏可视化设计.数码视讯展厅大屏可视化设计,在积累了一定经验的同时,也在不断的学习和丰富关于大屏设计的特点及数据可视化的表达方式. 数据可视化过滤了非常多的冗余信息,浓缩了最重要的信息,它的魅力就在于将枯燥的数据组织在一起,把最需要的那些编辑成一个故事.目前大数据那么流

算法设计与分析(屈婉玲)pdf

下载地址:网盘下载 算法设计与分析本教材为计算机科学技术专业核心课程"算法设计与分析"教材.<算法设计与分析>以算法设计技术和分析方法为主线来组织各知识单元,主要内容包括基础知识.分治策略.动态规划.贪心法.回溯与分支限界.算法分析与问题的计算复杂度.NP完全性.近似算法.随机算法.处理难解问题的策略等.书中突出对问题本身的分析和求解方法的阐述,从问题建模.算法设计与分析.改进措施等方面给出适当的建议,同时也简要介绍了计算复杂性理论的核心内容和处理难解问题的一些新技术. &

算法设计与分析-Week12

题目描述 You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the c