当前课程知识点:数据结构(上) >  第一章 绪论(上) >  (c)大O记号 >  01c-6: 2−Subset

返回《数据结构(上)》慕课在线视频课程列表

01c-6: 2−Subset在线视频

01c-6: 2−Subset

下一节:01c-7: 增长速度

返回《数据结构(上)》慕课在线视频列表

01c-6: 2−Subset课程教案、知识点、字幕

考察这样的一个问题

如果我们给定了n个正的整数

而且他们的总和正好是两倍的m

也就是说 是一个偶数

那么 作为一个整体

是否它存在一个其中的子集T

使得T中的元素的总和

是整体总和的一半?

那么其实这个言下之意就是说

不仅T中的元素总和是m

其实T的补集中的所有的元素的总和

也应该是等于m

或者简而言之 就是说

原来那n个整数 能否被恰好分成两部分

元素的个数可能未必相同

但是他们的总和都是各自为m

我们来看一下这个问题具体的一个模型和实例

我们来考察一下美国的大选

我们知道美国的大选 采用的是所谓的

选举人团这么样一个制度

也就是说 整个国家 按照行政区域的州

包括特区在内 划分成若干个区

具体来说 是51个区

每一个地区都有自己

由历史和包括人口等因素决定的

一个具体的选举人票数

各自有各自的分布

而在选举的过程中 每一州

都是要做各自独立的统计

如果某一选举人 在某一个州获胜

理论上讲只多出一票

也可以称他在对应的这个州获胜

而一旦他在某一个州获胜

这个州的所有的选举人票

比如说 对于马里兰来说 就是10票

对于加州来说 那就是55票

都会归入 这个候选人的名下

而最终确定谁能够当选

是由每一个候选人

所获胜的那些州的选举人票的总和

来相比较以后决定的

查看一下近年来选举的数据

我们可以发现 美国总共51个区

累计起来有538张票

换而言之 如果是有两个候选人的话

那么其中 只要有一个人

能够获得至少270张选举人票

那他就可以当选

这个不难理解

我们作为细节 要考虑的就是

会不会出现这么样一种特殊的情况呢?

也就是 如果这两位候选人恰好各得269票

那我们又该如何呢?

在回答这个问题之前

我们也许应该首先回答一个问题

就是 如果给定你这样一张表

由若干个州各自的选举人票

所构成的这样一张表

我们能否确定 肯定

有可能或者根本不可能出现

刚才我们说的这种

各自得恰好一半选票的情况呢?

这个问题 如果我们对照一下的话

其实就是我们刚才所说的

这个问题的一个特例

具体来说 在这里n

其实就是刚才的 50+1=51

而所有整数的数值

分别就是这51个区各自的选举人票数

我们看到 他们的总和538

确实是一个偶数

而我们所担心的那个问题

其实就是这个问题所询问的

是否有一个办法 能把所有的州

按照选举人分成两部分

使得它们各自所累积起来的选举人票

恰好是各自一半

在对这个问题有了这么样

一个具体模型的理解之后

我相信 大家很容易都会

马上得出一个直觉的算法

也就是说 我们逐一去枚举

S的每一个子集 并统计其中元素的总和

也就是说 我们针对其中的某一个候选人

去枚举出 他所有可能获胜的那些州的组合

并且统计出各自

每种情况下他所得的票的总和

如果一旦其中有发现得一半的

比如说269 在这种情况下

那么 我们就报告确实存在

这样的一种出现歧义的风险

否则的话 如果到最后也没有发现

我们就可以安然地说

根本不会出现这种情况

所以这种算法的正确性是毋庸置疑的

然而他的计算成本是多少呢?

我们不得不表示担心

因为理由是 我们注意到

我们所枚举的这些子集

相对于原来那个集合来说

就是不折不扣的所谓的幂集

而幂集的规模 就是原来那个集合的规模

相对而言的以2为底的指数

所以 其中这些要枚举

考察的这些实例的总数

其实就是一个指数规模的

而我们这个算法 刚才说过

必须要去逐一枚举它

换而言之 即使是从迭代的角度来看

最简单的情况 它也需要迭代这么多轮

换而言之 在最坏的情况下

它需要多达2的n次方这么多时间

这是一个我们刚才说需要回避的

所谓的指数复杂度的算法

有没有更好的办法呢?

有没有超过我们这种直觉更好的办法呢?

应该有 对吧?

但是结论是 没有

因为我们这里有一个定理

这样一个两个子集的划分问题

是一个典型的npc问题

NP-complete 什么意思呢?

我们在一些算法的理论课程里头

应该也许有介绍 在这里

我也简单把这个意思说一下

就目前所采用的计算模型而言

是不存在 可以在多项式时间内

求解这个问题的算法

除非 你对这个问题施加一些条件

比如说 最多的总数n不能超过多少

或者说 所有的那些元素的数值

也就是那个票数的分布

必须符合什么规律等等等等

如果不做这些假设的话

这个问题是不存在多项式的算法

所以 就这个意义而言

上述我们那种直觉的算法

居然已经是最优的了

然而很可惜 也很可悲的是

它只能是一个指数的算法

所以 从这里我们也可以看得出来

这种类似的问题 实际上是很多的

当然 它不是我们这个课讨论的重点

我们可以把所有的刻度汇总到一起

这样的话 我们就对整个这把直尺

以及上面的刻度 有了一个总体的 一个感觉

当然需要指出的是

这里同样 我们需要放眼长远

如果我们只是在一个相对比较小的尺度

比如像这个复杂度是从零到30的这个尺度

我们只观察局部的话

我们甚至可能会往往得出一个错误的结论

比如说 在这里

我们认为 最高复杂度的指数复杂度

在这里头 并不见得 体现的增长速度是最快的

原因很简单

因为我们这里的尺度太小

所以我们也许应该 换成一个更大的一个尺度

比如说 只要到大概2000以后 我们就可以看得出来了

比如说 刚才所说的指数复杂度 2的n次方

就可以在这地方 很明显地看出

虽然在小的尺度范围之内

它并不见得胜过

比如这里头的 n的立方

但是 毕竟 它的增长速度在足够远之后 是会体现出来的

它总有一天会超过 刚才所说的

所有这些固定阶次的多项式

所以 这也是我们从总体上 获得了这个标尺(的)一个感觉

在后边 我们将得到 更加具体的

针对具体问题的 一些这方面的感觉

数据结构(上)课程列表:

第零章

-选课之前

--写在选课之前

--宣传片

-考核方式

--考核方式

-OJ系统说明

--关于OJ

--1-注册与登录

--2-界面与选课

--3-提交测试

-关于课程教材与讲义

--课程教材与讲义

-关于讨论区

--关于讨论区

-微信平台

--html

-PA晋级申请

--PA晋级

--MOOC --> THU 晋级申请专区

--THU --> CST 晋级申请专区

--编程作业不过瘾?且来清华试比高!

第一章 绪论(上)

-(a)计算

--01-A-1: 计算

--01a-2: 绳索计算机

--01a-3: 尺规计算机

--01a-4: 算法

--01a-5 : 有穷性

--演示

--01a-6 : 好算法

--(a)计算--作业

-(b)计算模型

--01b-1: 性能测度

--01b-2: 问题规模

--01b-3: 最坏情况

--01b-4: 理想模型

--01b-5: 图灵机

--01b-6: 图灵机实例

--01b-7: RAM模型

--01b-8: RAM实例

-(b)计算模型--作业

-(c)大O记号

--01c-1: 主流长远

--01c-2: 大O记号

--01c-3: 高效解

--01c-4 : 有效解

--01c-5 : 难解

--01c-6: 2−Subset

--01c-7: 增长速度

-(c)大O记号--作业

第一章 绪论(下)

-(d)算法分析

--01d-1: 算法分析

--01d-2: 级数

--01d-3: 循环

--01d-4: 实例:非极端元素+起泡排序

--01d-5: 正确性的证明

--01d-6: 封底估算-1

--01d-7: 封底估算-2

-(d)算法分析--作业

-(e)迭代与递归

--01-E-1: 迭代与递归

--01-E-2: 减而治之

--01-E-3: 递归跟踪

--01-E-4: 递推方程

--01-E-5: 数组倒置

--01-E-6: 分而治之

--01-E-7: 二分递归:数组求和

--01E-8 二分递归:Max2

--01E-09: Max2:二分递归

-(e)迭代与递归--作业

-(xc)动态规划

--01XC-1: 动态规划

--01XC-2: Fib():递推方程

--01XC-3: Fib():封底估算

--01XC-4: Fib():递归跟踪

--01XC-5: Fib():迭代

--01XC-6: 最长公共子序列

-- 演示

--01XC-7: LCS:递归

--01XC-8: LCS:理解

--01XC-9: LCS:复杂度

--01XC-A: LCS:动态规划

-(xc)动态规划--作业

-本章测验--作业

第二章 向量(上)

-(a)接口与实现

--02A-1 接口与实现

--02A-2 向量ADT

--02A-3 接口操作实例

--02A-4 构造与析构

--02A-5 复制

-(a)接口与实现--作业

-(b)可扩充向量

--02B-1 可扩充向量

--02B-2 动态空间管理

--02B-3 递增式扩容

--02B-4 加倍式扩容

--02B-5 分摊复杂度

-(b)可扩充向量--作业

-(c)无序向量

--02C-1 概述

--02C-2: 循秩访问

--02C-3 插入

--02C-4 区间删除

--02C-5 单元素删除

--02C-6 查找

--02C-7 唯一化

--02C-8 遍历

-(c)无序向量--作业

-(d1)有序向量:唯一化

--02D1-1 有序性

--02D1-2 唯一化(低效版)

--02D1-3 复杂度(低效版)

--02D1-4 唯一化(高效版)

--02D1-5 实例与分析(高效版)

-(d1)有序向量:唯一化--作业

-(d2)有序向量:二分查找

--02D2-1 概述

--02D2-2 接口

--02D2-3 语义

--02D2-4 原理

--02D2-5 实现

--02D2-6 实例

--02D2-7 查找长度

-(d2)有序向量:二分查找--作业

第二章 向量(下)

-(d3)有序向量:Fibonacci查找

--02D3-1 构思

--02D3-2 实现

--02D3-3 实例

--02D3-4 最优性

-(d3)有序向量:Fibonacci查找--作业

-(d4)有序向量:二分查找(改进)

--02D4-1 构思

--02D4-2 版本B

--02D4-3 语义

--02D4-4 版本C

--02D4-5 正确性

-(d4)有序向量:二分查找(改进)--作业

-(d5)有序向量:插值查找

--02D5-1 原理

--02D5-2 实例

--02D5-3 性能分析

--02D5-4 字宽折半

--02D5-5 综合对比

-第二章 向量(下)--(d5)有序向量:插值查找

-(e)起泡排序

--02 E-1 构思

--02E-2 改进

--02E-3 反例

--02E-4 再改进

--02E-5 综合评价

-(e)起泡排序--作业

-(f)归并排序

--02F-1 归并排序:构思

--02F-2 归并排序:主算法

--02F-3 二路归并:实例

--02F-4 二路归并:实现

--02F-5 二路归并:正确性

--02F-6 归并排序:性能分析

-(f)归并排序--作业

-本章测验--作业

第三章 列表

-(a)接口与实现

--03A-1 从静态到动态

--03A-2 从向量到列表

--03A-3 从秩到位置

--03A-4 实现

-(a)接口与实现--作业

-(b)无序列表

--03B-1 循秩访问

--03B-2 查找

--03B-3 插入与复制

--03B-4 删除与析构

--03B-5 唯一化

-(b)无序列表--作业

-(c)有序列表

--03C-1 唯一化·构思

--03C-2 唯一化·实现

--03C-3 查找

-(c)有序列表--作业

-(d)选择排序

--03D-1 构思

--03D-2 实例

--03D-3 实现

--03D-4 推敲

--03D-5 selectMax()

--03D-6 性能

-(d)选择排序--作业

-(e)插入排序

--03E-1 经验

--03E-2 构思

--03E-3 对比

--03E-4 实例

--03E-5 实现

--03E-6 性能分析

--03E-7 平均性能

--03E-8 逆序对

-(e)插入排序--作业

-(xd)习题辅导:LightHouse

--03X D 习题辅导:LightHouse

-本章测验--作业

第四章 栈与队列

- (a)栈接口与实现

--04A-1 栈

--04A-2 实例

--04A-3 实现

- (a)栈接口与实现--作业

-(c1)栈应用:进制转换

--04C1-1 应用

--04C1-2 算法

--04C1-3 实现

-第四章 栈与队列--(c1)栈应用:进制转换

-(c2)栈应用:括号匹配

--04C2-1 实例

--04C2-2 尝试

--04C2-3 构思

--04C2-4 实现

--04C2-5 反思

--04C2-6 拓展

-(c2)栈应用:括号匹配--作业

-(c3)栈应用:栈混洗

--04C3-1 混洗

--04C3-2 计数

--04C3-3 甄别

--04C3-4 算法

--04C3-5 括号

-第四章 栈与队列--(c3)栈应用:栈混洗

-(c4)栈应用:中缀表达式求值

--04C4-1 把玩

--04C4-2 构思

--04C4-3 实例

--04C4-4 算法框架

--04C4-5 算法细节

--04C4−6A 实例A

--04C4−6B 实例B

--04C4−6C 实例C

--04C4-6D 实例D

-(c4)栈应用:中缀表达式求值--作业

-(c5)栈应用:逆波兰表达式

--04C5-1 简化

--04C5-2 体验

--04C5-3 手工

--04C5-4 算法

-第四章 栈与队列--(c5)栈应用:逆波兰表达式

-(d)队列接口与实现

--04D-1 接口

--04D-2 实例

--04D-3 实现

-第四章 栈与队列--本章测验

第五章 二叉树

-(a)树

--05A-1 动机

--05A-2 应用

--05A-3 有根树

--05A-4 有序树

--05A-5 路径+环路

--05A-6 连通+无环

--05A-7 深度+层次

-(a)树--作业

-(b)树的表示

--05B-1 表示法

--05B-2 父亲

--05B-3 孩子

--05B-4 父亲+孩子

--05B-5 长子+兄弟

-第五章 二叉树--(b)树的表示

-(c)二叉树

--05C-1 二叉树

--05C-2 真二叉树

--05C-3 描述多叉树

-(c)二叉树--作业

-(d)二叉树实现

--05D-1 BinNode类

--05D-2 BinNode接口

--05D-3 BinTree类

--05D-4 高度更新

--05D-5 节点插入

-(d)二叉树实现--作业

-(e1)先序遍历

--05E1-1 转化策略

--05E1-2 遍历规则

--05E1-3 递归实现

--05E1-4 迭代实现(1)

--05E1-5 实例

--05E1-6 新思路

--05E1-7 新构思

--05E1-8 迭代实现(2)

--05E1-9 实例

-(e1)先序遍历--作业

-(e2)中序遍历

--05E2-1 递归

--05E2-2 观察

--05E2-3 思路

--05E2-4 构思

--05E2-5 实现

--05E2-6 实例

--05E2-7 分摊分析

-第五章 二叉树--(e2)中序遍历

-(e4)层次遍历

--05E4-1 次序

--05E4-2 实现

--05E4-3 实例

-第五章 二叉树--(e4)层次遍历

-(e5)重构

--05E5-1 遍历序列

--05E5-2 (先序|后序)+中序

--05E5-3 (先序+后序)x真

-(e5)重构--作业

-本章测验--作业

第六章 图

-(a)概述

--06A-1 邻接+关联

--06A-2 无向+有向

--06A-3 路径+环路

-(a)概述--作业

-(b1)邻接矩阵

--06B1-1 接口

--06B1-2 邻接矩阵+关联矩阵

--06B1-3 实例

--06B1-4 顶点和边

--06B1-5 邻接矩阵

--06B1-6 顶点静态操作

--06B1-7 边操作

--06B1-8 顶点动态操作

--06B1-9 综合评价

-(b1)邻接矩阵--作业

-(c)广度优先搜索

--06C-1 化繁为简

--06C-2 策略

--06C-3 实现

--06C-4 可能情况

--06C-5 实例

--06C-6 多连通

--06C-7 复杂度

--06C-8 最短路径

-(c)广度优先搜索--作业

-(d)深度优先搜索

--06D-1 算法

--06D-2 框架

--06D-3 细节

--06D-4 无向图

--06D-5 有向图

--06D-6 多可达域

--06D-7 嵌套引理

-(d)深度优先搜索--作业

-第六章 图--本章测验

01c-6: 2−Subset笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。