【leetcode】【c++】378. Kth Smallest Element in a Sorted Matrix 以及 迭代器iterator的理解

首先是题目的介绍:

Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.

Note that it is the kth smallest element in the sorted order, not the kth distinct element.

Example:

matrix = [
   [ 1,  5,  9],
   [10, 11, 13],
   [12, 13, 15]
],
k = 8,
return 13.
Note: 
You may assume k is always valid, 1 ≤ k ≤ n2.

题目看起来也并不是很复杂,给了一个二维 n * n 的向量 vector,它的每一行和每一列都是按照递增的顺序进行排列的,要求求出该二维向量中按照大小排列第 k 位的元素,注意不是第 k 个元素,需要警惕的是虽然每行和每列都是按照大小进行排列,但是不同的一维向量之间并不是按照大小进行排列的,例如[ [ 2, 5], [4,6] ] 也是满足要求的,将它直接按照各一维向量顺序进行排列是不行的。

方法 1 :

首先我们来暴力解决这个题,利用stl 标准库函数中的 sort 函数进行所有元素的快排(注意 leetcode 是无需增加头文件声明的,直接调用即可),然后再取出第 k 个元素,下标为 k - 1即可。这个方法看起来确实挺笨的,耗时也相当的长,下面是这个问题的代码:

class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        vector<int> v;
        int len = 0;
        vector<vector<int>>::iterator it1;
        vector<int>::iterator it2;
        for(it1 = matrix.begin(); it1 != matrix.end();it1++)
        {
            for(it2 = (*it1).begin();it2 != (*it1).end();it2++)
            {
                len++;
                v.push_back(*it2);
            }
        }
        sort(v.begin(),v.end());
        return v[k - 1];
    }
};

如图可以看到:vector 的begin() 以及 end() 函数都是返回 iterator 迭代器类型,end() 是容器的最后元素的下一位置,成为超出末端迭代器,当容器为空时,begin() 与 end() 返回的迭代器相同,vector 实际上是一种能够存放任意类型的动态数组,能够增加和压缩数据,这一点非常重要以后可以以此啦代替数组的操作,转而用这种方法实现,当然毕竟不是真正的数组,当 oj 中要求是数组类型时,还要老老实实地用数组的方法去解决,vector的使用要在开头定义 #include<vector>; vector<int> v(n,elem)表示创造出含有 n 个相同元素elem的容器向量 v 。在本例中用到了二维的向量写法是 vector<vector<int>> .需要注意的是 sort(v.begin(),v.end()) ,而对数组 sort(a, a + len), len 是数组的全部元素个数,而不是元素个数-1,这是sort的规定,与end()是相互对应的,即指向最后一个元素下一位的指针类似的。

迭代器只能配合着容器使用,它实际是一种引用而不是指针,引用是变量的别名,而不是一个存储地址的存储单元,它不占用存储单元,和被引用的变量完全是一种意思,效果完全相同,都指的是存储变量所存储值的该存储单元的地址,而该存储单元的地址实实在在的存在于内存当中,使用时只需直接调用该地址即可,无需像指针那样特别声明。定义一个引用时必须同时进行初始化, 可以说迭代器又像指针又像引用,但与2者又有很大的不同,迭代器需要 *it 解引用,这一点和指针相同,但不能打印 it ,这又与指针不同;迭代器又返回的是对象的引用而不是对象的值或者是指针,这又和引用是一个意思,引用知识一个别名罢了,引用不能为空,而指针可以,因为引用在定义的同时必须要初始化,sizeof对指针操作得到的是指针的大小,对引用得到的是对象的大小,迭代器用完即被释放,而指针则可以继续存在。

另外讲一下 sizeof 的问题,strlen()字符串忽略末尾 ‘/0’,而sizeof() 则会记入,一个char占1 个字节,中文字符只有在字符串中才被当做2个字节对待。

下面是做的一些实验:

#include <algorithm>
#include <iostream>
#include<functional>
#include<vector>
using namespace std;


int main()
{
	//指针,引用以及迭代器的差别
	vector<int> v(10,1);
	vector<int>::iterator it;
	int i;
	cout << "各个 *it 分别为: " << endl;
	cout << "不能直接打印it,会报错" << endl;
	for (i = 0, it = v.begin(); it != v.end(); it++, i++)
	{
		cout << *it << " ";
		//获得的是实际是所引用的对象的内存单元的地址
		cout << "&it "<< &it << " ";
		//这里得到的既不是指针值也不是引用的对象的值,比较奇怪
		cout << "sizeof(it): "<< sizeof(it) << " ";
	}
	cout << endl;
	int num = 10;
	cout << "int num = 10, sizeof(num) : " << sizeof(num) << endl;
	//需要注意的是 int *p ,不能是 double *p 或者 long long ,这可能是计算机内部决定的
	int *p = &num;
	cout << "p (指针值,即num所在内存单元的地址) : " << p << endl ;
	cout << "&num (num所在内存单元的地址和p相同): " << &num << endl  ;
	cout << "*p : " << *p << endl ;
	int &quote = num;
	cout << "int &quote = num 后的 quote :  " << quote << endl ;
	cout << "&quote (quote实际就是num的别名和num意义完全相同,因此地址也与num相同)为: " << &quote << "\n";
	cout << "*quote 不能实现,会报错quote不是指针" << endl;
	cout << "sizeof(num): " << sizeof(num) << endl;
	//32位机中,指针的size返回值必定是4个字节,与指针指向的对象没有任何的关系
	cout << "指针的size, sizeof(p): "<<sizeof(p) << endl;
	//对引用得到的是对象的大小
	cout << "引用的size, sizeof(quote): " << sizeof(quote) << endl;

	//sizeof问题
	cout << "sizeof(int): " << sizeof(int) << endl;
	cout << "sizeof(char): " << sizeof(char) << endl;
	cout << "不能直接 cout sizeof(vector) 会报错" << endl;
	int a[10] = {1,2};
	cout << "初始化 int a[10] = {1,2} 打印数组 a 为:  " << endl;
	for (int i = 0; i < 10; i++)
		cout << a[i] << " ";
	cout << endl;
	cout << "sizeof(a) / 4 : " << sizeof(a) / 4  << endl;
	char s1[3] = "hi";
	cout << "sizeof(s)(对于字符串来说sizeof(char s1[3] = 双引号hi)) : "<< sizeof(s1) << endl;
	cout <<"sizeof(双引号hi): "<< sizeof("hi")  << endl;
	char s2[] = {'h','i'};
	cout << "sizeof(char s2[] = {h, i单引号}): " << sizeof(s2)  << endl;
	cout << "sizeof(h 单引号): " << sizeof('h')  << endl;
	char s3[] = { '你','好' };
	cout << "sizeof(char s3[] = {你,好 单引号}): " << sizeof(s3)  << endl;
	cout << "sizeof(你好 双引号): " << sizeof("你好") << endl;
	//char 一个字母“”或者{“”} 用双引号都是错误的
	char c1 = '你';
	//只要是char都是占一个字节,只有是在字符串中一个中文字符占2个字节
	cout << "sizeof(你 单引号): " << sizeof(c1) << endl;
	return 0;
}

运行结果:

各个 *it 分别为:
不能直接打印it,会报错
1 &it 00CFF8C8 sizeof(it): 12 1 &it 00CFF8C8 sizeof(it): 12 1 &it 00CFF8C8 sizeof(it): 12 1 &it 00CFF8C8 sizeof(it): 12 1 &it 00CFF8C8 sizeof(it): 12 1 &it 00CFF8C8 sizeof(it): 12 1 &it 00CFF8C8 sizeof(it): 12 1 &it 00CFF8C8 sizeof(it): 12 1 &it 00CFF8C8 sizeof(it): 12 1 &it 00CFF8C8 sizeof(it): 12
int num = 10, sizeof(num) : 4
p (指针值,即num所在内存单元的地址) : 00CFF8B0
&num (num所在内存单元的地址和p相同): 00CFF8B0
*p : 10
int &quote = num 后的 quote :  10
&quote (quote实际就是num的别名和num意义完全相同,因此地址也与num相同)为: 00CFF8B0
*quote 不能实现,会报错quote不是指针
sizeof(num): 4
指针的size, sizeof(p): 4
引用的size, sizeof(quote): 4
sizeof(int): 4
sizeof(char): 1
不能直接 cout sizeof(vector) 会报错
初始化 int a[10] = {1,2} 打印数组 a 为:
1 2 0 0 0 0 0 0 0 0
sizeof(a) / 4 : 10
sizeof(s)(对于字符串来说sizeof(char s1[3] = 双引号hi)) : 3
sizeof(双引号hi): 3
sizeof(char s2[] = {h, i单引号}): 2
sizeof(h 单引号): 1
sizeof(char s3[] = {你,好 单引号}): 2
sizeof(你好 双引号): 5
sizeof(你 单引号): 1
请按任意键继续. . .

 再回到我们的程序中来,程序中迭代器必须要用(*it). 用括号括起来,否则会报错,本题中 *it 表示的是一个vector。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值