刷leetcode第一天!
第一道题目:两数之和
给定一个整数数组 nums
和一个目标值 target
,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
初级版:
两层循环,时间复杂度为0(n²),找到即返回,这种情况下没有考虑到一个数组里面存在两对答案的可能。
知识点:
C++
Vector类(push_back与pop_back比较常用)
注意vector中size()与opacity()的不同。size是当前向量的长度,opacity指容量,当当前长度大于容量时,会自动扩容,应该要尽量避免这种情况,指定足够的容量或者动态。
读取可以通过下标读取,也可通过迭代器。当vector尚为赋值时,无法通过下标读取。注:不可通过nums+i这种数组方式读取!vector的内存分配不在一起,不像数组!
特别注意vector的传值。
1、形参传值
vector<int> nums(10,0);
void test( vector<int> elements ); //接受一个数组,这种情况下进行拷贝传值,在函数中对数组的更改不会影响实参。
void test( vector<int>& elements ); //接受一个数组的引用,形参作为实参的别名,改变形参即改变实参,调用时:test( nums );
void test( vector<int>* elements ); //接受一个指针/地址,拷贝传值(拷贝的是数组的地址),改变地址中的值即改变实参的值。调用时为:test( &nums ); //注意区分vector与数组,数组名为数组头地址,vector不一样,所以需要取地址符号。若为vector<int >* tmp(nums);那么调用方式为test( tmp );
2、返回值传值
vector<int> test(){...return nums;} //返回一个向量类型,产生拷贝构造。
vector<int>* test(){ vector<int>* tmp= new vector<int>[10];....return tmp}; //必须为指针分配存储空间,否则传回来的指针是野指针。
vector<int>& test(){vector<int>* tmp= new vector<int>[10];....return *tmp};
但二维还是用数组表示比较方便?
异常抛出(不熟,需要学习加强)
高级版:哈希表
哈希表就是将关键字与值进行配对,在这道题中就是数组中数字的值与它的索引进行配对。
那么算法的基本思想就是建立哈希表,然后在循环中用哈希表查找对应的键值。有两边哈希表与一遍哈希表两种用法。
空间复杂度与时间复杂度都为n。
哈希表的数据结构(关键在于散列函数)
知识点:
Java当中
1、Map
Map是一个接口,是键值对映射的抽象接口。关于Map的介绍,详情见Java 集合系列14之 Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)
2、HashMap
Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例 (没咋看懂,要学的还是太多了)
C++当中
map,STL中提供的一种一对一的关联容器,实际上也是哈希表,使用方式:
map<int,int>element;
-------------------------
第二道题目:整数反转
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
JAVA解答
这道题如果不考虑溢出的话非常简单。但溢出的考虑就比较麻烦了。可以通过try-catch的方式来写,但是这种方式调用大量库函数,比计算更慢。
更好的方式是通过计算来考虑整数的溢出,使用java中integer类的最大值与最小值进行计算就可以了:
class Solution {
public int reverse(int x) {
int reverse = 0;
while (x != 0) {
int tmp = x % 10;
if (reverse > Integer.MAX_VALUE / 10 || (reverse == Integer.MAX_VALUE / 10 && pop > 7))
return 0;
if (reverse < Integer.MIN_VALUE / 10 || (reverse == Integer.MIN_VALUE / 10 && pop < -8))
return 0;
reverse = reverse * 10 + tmp;
x /= 10;
}
return reverse;
}
}
其中,7是2^31-1的个位数,-8是-2^31的个位数。
C++解答
在C++中,吧Integer.MAX_VALUE换成INT_MAX与INT_MIN即可
------------------------------------------------------
第三道题目:回文数
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
进阶:
你能不将整数转为字符串来解决这个问题吗?
初级版
这个问题的初级版解答算是整数反转的进阶,即将整数反转之后看看与原数是否相等。
但是在答案核对中,这种方法需要考虑整数溢出问题。按道理,反转后会产生整数溢出的数都不是回文数。所以应当直接返回false,而不是还需要判断来处理溢出。
高级版
取后半段数字进行反转与前半段比较
具体做法如下:
每次进行取余操作 ( %10),取出最低的数字:y = x % 10
将最低的数字加到取出数的末尾:revertNum = revertNum * 10 + y
每取一个最低位数字,x 都要自除以 10
判断 x 是不是小于 revertNum ,当它小于的时候,说明数字已经对半或者过半了
最后,判断奇偶数情况:如果是偶数的话,revertNum 和 x 相等;如果是奇数的话,最中间的数字就在revertNum 的最低位上,将它除以 10 以后应该和 x 相等。