用C++写的,感觉处理起来要比py舒服
数据结构与算法
数据结构
逻辑结构
数据元素之间的相互关系
- 集合结构:无序的,仅由类似特性的元素共同组成
- 线性结构:一对一的,数据由一个数据引出,同时最多导向一个数据
- 树形结构:一对多的,有层次的
- 图形结构:多对多的,由节点构成的,各个节点之间可能都会有关系
物理结构
数据在计算机中的存储方式
- 顺序存储:放在一块连续的内存里面,像数组那样,方便易得,但是不易进行修改插入操作
- 链式存储:将数据放在任意的存储单元里,这些数据有可能相邻,也有可能不,可以方便的进行管理与修改,但是指针和内存空间都会需要空间,可能会比顺序存储大
算法
可以认为是完成某个事件的步骤吧
算法的基本特性
- 输入:要有输入给算法的参数
- 输出:要有这个算法的结果
- 有穷性:这个算法得有个头,不可以无限制的跑下去,要在有穷的步骤内跑完,并且消耗的时间要合理
- 确定性:每一步之间不应该存在歧义
- 可行性:写出来的算法要在电脑上跑得动
算法的目标
- 空间复杂度低:吃运行内存吃得少
- 时间复杂度低:跑程序跑得快
本质上就是马一样的,吃得多跑得快,或吃得少跑得还行,虽然做不到又吃得少跑得还快,但是在二者间达到一个优质的点还是可以的
其他的目标
- 正确性:跑程序跑得是对的
- 可读性:是人看得懂的,不要给后面的人找麻烦
- 健壮性:对于错误操作和非法数据有一定处理能力,不容易玩崩
复杂度
时间复杂度
在输入规模为n的情况下,算法运行所需要消耗的时间,记为T(n)
有渐近紧确界,渐近上界,渐近下界之分,而通常分析以分析渐近上界为主
计算时间复杂度
- 加法:相加取最大,取量级最大的那个的时间复杂度作为结果
- 乘法:循环嵌套复杂度相乘
- 递归:似乎有人写着说复杂度为递归数*每次递归中复杂度
复杂度分类
- O(1):运行时间不随问题规模变化
- O(n):运行时间随问题规模线性变化,单层循环等
- O(n^2): 一般是循环双层嵌套,随着问题规模增大,运行时间随n^2线性增大
- O(n!):随问题规模增大,运行时间呈阶乘增长
- O(logn):通常是二分法或分治法等的时间复杂度,这种通常是比较理想的
- O(nlogn):线性对数,通常出现在排序算法中,外层logn复杂度,内层n复杂度
一般来说,O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(2^n)<O(n!)<O(n^N)
最佳、最坏、平均时间复杂度
通常来说用其中之一,学校里教的用最坏的,因为最好的和平均的难以估量,而最坏的可以直接进行计算,但是这里用的平均复杂度
空间复杂度
输入的规模为n的情况下,算法所占用的空间大小,记作S(n)
包括「局部变量(算法范围内定义的变量)所占用的存储空间」和「系统为实现递归(如果算法是递归的话)所使用的堆栈空间」两个部分。
分类
- O(1):不会随规模变化而发生空间复杂度的改变
- O(n):通常发生在递归调用
由大小排序可得,O(1)<O(logn)<O(n)<O(n^2)<O(2^n)
例题代码
T2235
class Solution {
public:
int sum(int num1, int num2) {
return num1 + num2;
}
};
T1929
class Solution {
public:
vector<int> getConcatenation(vector<int>& nums) {
int n = nums.size();
vector<int>ans(n*2);
for(int i = 0;i < n;i++)
{
ans[i] = nums[i];
}
for(int i = n;i < 2*n;i++)
{
ans[i] = nums[i-n];
}
return ans;
}
};
T771
class Solution {
public:
int numJewelsInStones(string jewels, string stones) {
int count = 0;
for(int i = 0;i < stones.size();i++)
for(int j = 0;j < jewels.size();j++)
if(stones[i] == jewels[j])count++;
return count;
}
};
T1480
头一次玩vector,这玩意和以前学的数组还挺不一样
class Solution {
public:
vector<int> runningSum(vector<int>& nums) {
vector<int>res;
int temp;
for(int i = 0;i < nums.size();i++)
{
temp += nums[i];
res.push_back(temp);
}
return res;
}
};
T709
class Solution {
public:
string toLowerCase(string s) {
for(int i = 0;i <= s.size();i++)
{
s[i] += 32;
}
return s;
}
};
也有直接调用小写化的,还有一种利用位操作的 |=32 这样的方法
T1672
int maximumWealth(int** accounts, int accountsSize, int* accountsColSize){
int max = 0;
for(int i = 0;i < accountsSize;i++)
{
int sum = 0;
for(int j = 0;j < *accountsColSize;j++)sum += accounts[i][j];
if(sum > max) max = sum;
}
return max;
}
力扣的刷题方式还是很有特色的,虽然大部分时候最大的问题还是不明白函数里给的接口是什么意思QAQ