A
Leetcode算法题(easy)
我的代码如下:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> result;
for (int i = 0; i < nums.capacity(); i++) {
for (int j = i + 1; j < nums.capacity(); j++) {
if (nums[i] + nums[j] == target) {
result.push_back(i);
result.push_back(j);
}
}
}
return result;
}
};
由于本题使用了vector,于是在网上查询了一些基本的使用方法,除了一些特殊的成员函数之外,与数组的使用大同小异。当然,对于vector一类的迭代器,利用下标访问虽然可行,但是直接使用begin()
、end()
等是更典型的做法。
我的提交结果如下:
很明显,运行时间的差距十分显著,于是再对比运行时间较短者(代码如下):
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> indices;
for (int i = 0; i < nums.size(); i++) {
if (indices.find(target - nums[i]) != indices.end()) {
return {indices[target - nums[i]], i};
}
indices[nums[i]] = i;
}
return {};
}
};
- 可以发现,该作者并不是使用vector进行操作,而是使用了
map
这一迭代器。搜寻相关资料,发现map
这一迭代器最大的特点在于其为一键值对,类似python
中的字典。这一迭代器在此题目中的最大优势在于它的查找功能,利用find()
可以更快地找到目标元素并操作;参照其他运行时间短的代码,发现这些代码普遍使用了map
迭代器。 - 而在我的代码中,我使用的为
vector
迭代器,在查找元素时,利用了两层的for循环嵌套,当数据量较大时,显然极为不利。 - 总结:对于元素的查找,使用
map
中的find()
能具有更高的效率。
R
本周阅读文章:Zero-shot learning:Using text to more accurately identify images
- 研究内容:本文主要讲述的是零镜头学习,是一种使用文本更准确地识别图像的机器学习。零镜头学习(ZSL)是机器学习认知它从未见过的对象的过程。Facebook的研究者开发了一种新的、更精确的ZSL模型,它使用被称为对抗神经网络(GANS)的神经网络框架来阅读分析文本,然后将文本中所描述的对象可视化识别。与其他模型将每一个对象独立分开地学习不同,这种新颖的ZSL方法使机器得以根据种类将对象进行分类处理,然后再使用这些信息识别其他相似对象。
- 工作方式:研究人员训练了这个模型,称为对抗零镜头模型 (GAZSL),它依据两个包含了60,000多个图象的数据库,识别了超过600多种鸟类。接着,再让它读取网络文章,让它使用文章上的信息识别它从未识别过的鸟类。这个模型从该文本中提取了七个关键的视觉特点,将这些特点合成可视化,并使用这些特征识别正确的鸟类。之后,研究人员将GAZSL模型与其他七个ZSL算法模型测试比较,它再四个不同的基准中始终更为精确。总体上看,GAZSL模型的表现相较其他模型要优于4%~7%,有时甚至要好得更多。
- 其重要性:为了变得更有效用,计算机的可视化系统需要识别它们从来没有被特殊训练过的对象。例如:据估计,共有10,000种存活的鸟类,但是大多数计算机的视觉数据中只包含了几百种的鸟类。这种新的开源的ZSL模型已被证实可以产生更好的结果,并为未来的机器学习研究提供了一条有希望的道路。许多AI的研究依旧是基础性的,但是如何改进系统理解文本的方式以及正确识别对象的工作,仍然是为更好、更可信的AI系统打基础。
本文主要介绍了Facebook的研究人员开发的一种新的机器学习的方法,它能有效地通过对图像以及文本的学习(尤其是对文本的学习)对机器从未学习过的对象并分类,是一种非常优秀的方法。
T
本周,程序设计课程迎来了上机期中考,发现了一个极易被我忽视的问题。在考题中其中的一题题目为:定义一个类PowerArray
,该类是一个强大的数组类,包含一个私有成员int *ptr
,指向实际的存储数组元素的地址空间,用户在构造该类对象时需要指定数组的大小作为参数,然后根据大小从堆中分配空间。 该类还需包含一个成员函数countElement()
,返回当前实际存储的数组元素的个数。仔细考虑需要定义哪些成员函数,在Main中进行充分测试。
我写了如下代码:
class PowerArray {
private:
int len;
int *ptr;
int count;
public:
PowerArray(int size);
~PowerArray();
int countElement();
void get_number(int i);
};
PowerArray::PowerArray(int size) {
len = size;
ptr = new int[size];
count = 0;
}
PowerArray::~PowerArray() { delete[] ptr; }
void PowerArray::get_number(int i) {
if (count <= len) {
ptr[count] = i;
count = count + 1;
}
else {
cout << "OUT OF RANGE!" << endl;
}
}
int PowerArray::countElement() { return count; }
我使用了get_number()
函数获取数值,再利用countElement()
记录当前数组内的元素个数,经充分检验运行正常;之后,我打算再为这个类添加一个新的功能:该数组类能获取一个新的数组里的全体元素,并对当前数组内所含元素计数,加入的代码如下:
class PowerArray {
private:
//---(此处省略)
public:
//---(此处省略)
void get_array(int &a); //添加数组功能的函数
};
//---(此处省略)
//添加数组功能的函数
void PowerArray::get_array(int &a) {
if (count <= len) {
for (int j = 0; j < sizeof(a); j++) {
ptr[count] = a[j];
count++;
cout << count << endl;
}
} else {
cout << "OUT OF RANGE!" << endl;
}
}
- 本以为一切都能够正常运行,但是却出现了严重的问题:经检验,发现
sizeof(a)
的值并不是想象中的数组长度,实际运行结果为4。 - 问题在于:当我将数组名作为参数传递时,传递到函数内的参数其实是数组首地址(一个指针变量),而不是想象中的仍然作为一个数组名处理。即:用参数传递数组名时,数组名退化为指针。
- 换言之,当
array
只作为数组名处理时,sizeof(array)
返回的值是数组元素 * 每个元素数据类型的长度
;而在作为参数传至至函数后,sizeof(array)
的操作实际等效于sizeof(array[0])
,即返回了首元素的地址变量(int
类型)的长度,结果为4。
结论:简单地在将数组名用作参数传递的做法显然并不明智,如要使用此方法,应当先知道数组的长度,并在将数组名作为参数传递时使用如下方法:void get_array(int (&a)[N])
(其中N为数组长度);另一方法是使用模板操作。
S
- 由于临近期中考,本周暂未学习新的算法,仅进行了一些简单的复习,敲代码时间严重不足。
下周目标:- 固定每天的学习时间,目标可根据下周的考试复习任务、每天的作业量更改,但是每天必须有必要的学习和思考;
- ARTS的任务最好能在每天有所想法时添加,多次分工,而非一次性写完,如此耗时费力;
- 算法仍然需要大量投入时间学习:根据这几次Leetcode的题目提交结果来看,时间普遍过长,如此低效的算法显然是不行的,仍需多加学习和总结。
- 推荐网页:Facebook AI