leetcode刷题笔记Day1

leetcode刷题笔记Day1

1、两数之和

题目描述:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

解法一:暴力求解

思路:

1、遍历每个元素A,寻找合适的数字B组成target;

2、数字B可以从元素A往后的元素中寻找;

代码:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> v;
        for (int i = 0; i < nums.size()-1;i++) {
            for (int j = i + 1; j < nums.size(); j++) {
                    if (nums[j] + nums[i] == target) {
                        v.push_back(i);
                        v.push_back(j);
                    }
            }
	    }
        return v;
    }
};

结果:

在这里插入图片描述

解法二、哈希查找

思路:

1、解法一的局限性在于寻找元素B费时,所以为降低空间复杂度,我们需要做的就是缩短寻找元素B的时间,简单来讲就是选择时间复杂度最低的元素查找算法。

2、查找算法中,时间复杂度最小的是哈希查找,当然,也可以选择其他查找算法,只要时间复杂度低于要求的O(n2)

3、利用HashMap实现

代码:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> v;
        unordered_map<int, int> hash;
        for (int i = 0; i < nums.size(); i++) {
            auto it = hash.find(target - nums[i]);
            if (it != hash.end()) {
                //先插入it->second的原因是最初始哈希表中是空的,当我们找不到元素后,会将该元素直接插入到哈希表中,这就导致了元素B位置是位于元素A前面
                v.push_back(it->second);
                v.push_back(i);
                return v;
            }
            //将数组中元素的值作为key值,是因为map<key,value>查找是根据key来查找的,而不是value,我们是需要按值查找的,因此将元素的值作为key,元素下标作为value
            hash[nums[i]] = i;
        }
        return {};
    }
};

结果:

在这里插入图片描述

相关容器介绍

vector

定义:

表示可变大小数组的序列容器,可以通过下标来访问元素,和数组十分类似

用法:

//包含头文件
#include<vector>
/***************************************************************************************/
//构造
vector<datatype> name;//空vector
vector(int nSize);//创建一个vector,元素个数为nSize
vector(int nSize,const t& t);//创建一个vector,元素个数为nSize,且值均为t
vector(const vector&);//复制构造函数
vector(begin,end);//复制[begin,end)区间内另一个数组的元素到vector中
/***************************************************************************************/
//增加
name.push_back(data);//向量尾部增加一个元素X
terator insert(iterator it,const T& x);//向量中迭代器指向元素前增加一个元素x
iterator insert(iterator it,int n,const T& x);//向量中迭代器指向元素前增加n个相同的元素x
iterator insert(iterator it,const_iterator first,const_iterator last);//向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据
/***************************************************************************************/
//插入,insert不支持根据下标去插入
vector<int> v(10, 10);// 用10个10来初始化vector
v.insert(v.begin() + 3, 11);// 在第三个位置插入11
vector<int> v(10, 10);
v.insert(v.begin() + 2, 5, 2);// 在第二个位置往后连续插入5个2
/***************************************************************************************/
//删除,erase不支持根据下标去删除
vector<int> v(10, 10);
v.erase(v.begin()+3);// 删除第3个位置的值
vector<int> v(10, 10);
v.erase(v.begin() + 2, v.begin() + 6);// 删除第2个位置到第6个位置的所有值
void pop_back();//删除向量中最后一个元素
void clear();//清空向量中所有元素
/***************************************************************************************/
//遍历
reference at(int pos);//返回pos位置元素的引用
reference front();//返回首元素的引用
reference back();//返回尾元素的引用
iterator begin();//返回向量头指针,指向第一个元素
iterator end();//返回向量尾指针,指向向量最后一个元素的下一个位置
reverse_iterator rbegin();//反向迭代器,指向最后一个元素
reverse_iterator rend();//反向迭代器,指向第一个元素之前的位置
//直接像数组一样,name[i]来表示
/***************************************************************************************/
//大小
int size() const:返回向量中元素的个数
/***************************************************************************************/
//交换
void swap(vector&);//交换两个同类型向量的数据
/***************************************************************************************/
//排序
#include <algorithm>
sort(name.begin(),name.end());//从小到大
reverse(obj.begin(),obj.end());//从大到小
/***************************************************************************************/
//定义二维数组
/*resize 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值
  reserve 改变当前vecotr所分配空间的大小*/
/*方法一*/
int N=5, M=6; 
vector<vector<int> > obj(N); //定义二维动态数组大小5行 
for(int i =0; i< obj.size(); i++)//动态二维数组为5行6列,值全为0 
{ 
   obj[i].resize(M); 
}
/*方法二*/
int N=5, M=6; 
vector<vector<int> > obj(N, vector<int>(M)); //定义二维动态数组5行6列    
Map

定义:

map是STL的一个关联容器,以键值对存储的数据,其类型可以自己定义,每个关键字在map中只能出现一次,关键字不能修改,值可以修改;

用法:

//包含头文件
#include<map>
/***************************************************************************************/
//定义
map<int,string> my_map;
/***************************************************************************************/
//插入
/*第一种*/
my_map.insert(pair<int,string>(1,"first"));//插入pair数据
/*第二种*/
my_map.insert(map<int,string>::value_type(1,"first"));//插入value_type数据
/*第三种*/
my_map[1]="first";//数组直接赋值
/***************************************************************************************/
//查找
my_map.count(1);//用count函数判断关键字是否存在,没办法定位元素位置
my_map.find(1);//用find函数定位元素位置
/*通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据iterator->first和iterator->second,分别代表关键字和value值*/
/***************************************************************************************/
//删除
map<int, string>::iterator it;  
it = my_map.find(1);  
my_map.erase(it); //用关键字删除单个元素
my_map.erase( my_map.begin(), my_map.end() ); //整体删除
/***************************************************************************************/
//排序
/*map中元素是自动按key升序排序(从小到大)的;
按照value排序时,想直接使用sort函数是做不到的,sort函数只支持数组、vector、list、queue等的排序,无法对map排序,那么就需要把map放在vector中,再对vector进行排序。*/
vector< pair<string,int> > vec(ma.begin(),ma.end());
sort(vec.begin(),vec.end(),cmp);
HashMap

定义:

C++中实现哈希表可以用unordered_map来实现

用法:

//包含头文件
#include <unordered_map>
//定义:
//和map基本一致,只是换为unordered_map而已

哈希查找

按照关键字为每一个元素"分类",然后将这个元素存储在相应"类"所对应的地方。

哈希表是一个在时间和空间上做出权衡的经典例子。如果没有内存限制,那么可以直接将键作为数组的索引。那么所有的查找时间复杂度为O(1);如果没有时间限制,那么我们可以使用无序数组并进行顺序查找,这样只需要很少的内存。哈希表使用了适度的时间和空间来在这两个极端之间找到了平衡。只需要调整哈希函数算法即可在时间和空间上做出取舍。

2、回文数

题目描述:

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false

回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

示例:

输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

解法一、转字符串

思路:

1、将数字转化为字符串,然后对比下标为 i 的元素和下标为 length-1-i 的元素是否一样,若一样,则是回文数,否则,就是非回文数。

代码:

class Solution {
public:
    bool isPalindrome(int x) {
        string str = to_string(x);
        int len = str.length();
        for (int i = 0; i < len/2; i++) {
            if (str[i] == str[len - 1 - i]) {
                continue;
            }
            else {
                return false;
            }
        }
        return true;
    }
};

结果:
在这里插入图片描述

解法二、数字处理

思路:

1、解法一内存占比大,是因为我们需要另外的空间来存储整数转化后的字符串,为了降低内存,我们可以直接用数字处理,不转化字符串。

2、考虑特殊情况:

  • 负数一定不是回文数;
  • 非0整数,个数位为0也一定不是回文数;

3、在除上述两种情况下,如何利用数字来判断回文数?

不论是数字长度是奇数还是偶数,只要后半部分的数字倒装后与前半部分数字相等,那就是回文数。
例如:12321,后半部分数字倒装后为12,前半部分为12,则为回文数。

&如何获取后半部分倒装后的数字以及前半部分数字?

除10取余法
. 1、后半部分数字:获取每一位数字,逐步除10取余数;
. 2、后半部分倒装:逐步乘10相加;
. 3、前半部分数字:在第一步中每次除10剩余部分就是前半部分数字;
. 4、结束循环条件:前半部分数字位数小于或等于后半部分位数,但是这种位数判断需要另外的代码,费时费空间,所以我们可大致看为数字大小,前半部分数字小于后半部分数字,循环结束。

代码:

class Solution {
public:
    bool isPalindrome(int x) {
        if (x < 0) {
            return false;//负数
        }
        else if (x == 0) {
            return true;
        }
        else {
            if (x % 10 == 0) {
                return false;//末尾为0的数
            }
            else {
                int late = 0;
                while (x > late) {
                    late = late * 10 + x % 10;//后半部分数
                    x /= 10;//前半部分数字
                }
                if (x == late) {
                    return true;//整数为偶位数
                }
                else if(x==late/10){
                    return true;//整数为奇位数
                }
                else {
                    return false;
                }
            }
        }
    }
};

结果:
在这里插入图片描述

注意:还不如第一种方法,但是我去看了官方题解,以及在评论中也试了别的代码,发现原理大致就这两种,且结果似乎都是这样,暂时找不到什么能够降低内存的方法。

相关知识

数值与string相互转换

数值转string:

to_string()函数

用法:

//包含头文件
#include<string>

string转数值:

用法:

//包含头文件
#include<stdlib.h>
//string转int
string love="77";
int ilove=atoi(love.c_str());
//string转float或double
string love="77.77";
float fLove=atof(love.c_str());
double dLove=atof(love.c_str());

相关知识

数值与string相互转换

数值转string:

to_string()函数

用法:

//包含头文件
#include<string>

string转数值:

用法:

//包含头文件
#include<stdlib.h>
//string转int
string love="77";
int ilove=atoi(love.c_str());
//string转float或double
string love="77.77";
float fLove=atof(love.c_str());
double dLove=atof(love.c_str());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值