代码随想录
https://www.programmercarl.com/
编程素养
代码风格
C++代码风格参考google C++ style Guide
我使用的是驼峰命名法,其中空格留白的规则如下例:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
if (nums[fastIndex] != 0) {
nums[slowIndex++] = nums[fastIndex];
}
}
for (int i = slowIndex; i < nums.size(); i++) {
nums[i] = 0;
}
}
};
- 操作符左右有空格
- 分割符
, ;
后有空格,类似于写英文文章 - 控制语句后有空格
- 大括号和函数保持在同一行 (Google规范是 大括号和 控制语句保持同一行的)
写算法题目是否用库函数的标准是什么?
如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。
如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,那么直接用库函数。
使用库函数最大的忌讳就是不知道这个库函数怎么实现的,也不知道其时间复杂度,上来就用,这样写出来的算法,时间复杂度自己都掌握不好的。
例如for循环里套一个字符串的insert,erase之类的操作,你说时间复杂度是多少呢,很明显是O(n^2)的时间复杂度了。
在刷题的时候本着我说的标准来使用库函数,相信对大家回有所帮助!
算法性能分析
时间复杂度
什么是时间复杂度? 时间复杂度是一个函数,它定性描述某个算法的运行时间。
对于一个算法(或者程序)我们通常会估算它的操作单元数量(例如排序中的比较操作)来代表程序消耗的时间;
假设算法的问题规模为n(即操作的最小数据元素为n。例如排序问题中待排序列长度为n),则得到该问题规模下操作单元数量计算公式f(),那么对于问题规模为n的模型,操作单元数量的计算公式为f(n),其中,随着数据规模n的增大,算法执行时间的增长率
和f(n)的增长率相同,这一现象中的增长率称作为算法的渐近时间复杂度,简称时间复杂度,记为 O(f(n))。
其中,O代表上界的
,当用它作为算法的最坏情况运行时间的上界,就是对任意数据输入的运行时间的上界。
算法超时问题
首先,算法是否超时喝计算机的配置有关,1GHz=10亿Hz (Hz是赫兹单位)
1Hz 是CPU的一次脉冲(可以理解为一次改变状态,也叫时钟周期),1Hz=1/s,就是一秒1次脉冲,10亿Hz,就是一秒10亿次脉冲。并不是说1次脉冲代表一次计算机的运算,例如对于一个加法运算,cpu要执行四次才能完整这个操作,步骤一:把1放入寄存机,步骤二:把2放入寄存器,步骤三:做加法,步骤四:保存3。 同时存在有多个程序使用CPU的情况。
那我们的计算机究竟1/s能经过多少次运算呢,可以通过代码测试:测试硬件:2015年MacPro,CPU配置:2.7 GHz Dual-Core Intel Core i5 。
1s能进行k++操作 5 × 1 0 8 5\times10^{8} 5×108次。
C/C++基础
#include<iostream>
#define N 10
void sort(int a[], int n);//这里因为代码中方法函数的调用先与定义,因此要声明,反之不用
void print(int a[], int n);
//主函数部分
void main(){
int a[N];
cout<<"input 10 numbers:\n";
for (int i = 0;i<N; i++)
cin>>a[i];
sort(a,N)
print(a,N);
}
//方法函数定义部分
void sort(int a[], int n){
for (int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
if(a[i]<a[j]){
int t=a[i];
a[i]=a[j];
a[j]=t;
}
}
}
}
//方法函数定义部分
void print(int a[], int n){
for (int i=0; i<n; i++)
cout<<a[i]<<" ";
cout<<endl;
}
首先,来个整体说明,对于一个C++的程序,需要有三部分
- 声明部分
- 主函数部分
也就是Main函数部分 - 函数定义部分
函数定义部分用来定义函数的功能,所有在前面只做了生命的函数都必须在此处进行定义。
其次,我们对代码中的细节进行逐条说明
- C++支持c语言中的注释方式
/*内容*/
;在此基础上增加了行注释符号//
,它可以出现在一个行的任何位置,其有效范围是从符号开始到这一行结束。 - 每一句程序需要使用
;
表示其结束 - C++中使用cin进行输入数据,cout输出数据,他们的定义在
<iostream.h>
中,引入这个头文件即可,或者引入c++标准头文件<iostream>
效果等价。cin输入数据到内存中的变量中,cout输出数据到屏幕上。 - 因为在main()函数中使用sort()和print()函数时,还没定这两个函数的定义,因此需要在开头生命这两个函数,包括1.返回值类型2.函数名3.形式化参数变量
- 对于主函数,同C程序一样,C++必须有一个主函数。
例子2
https://leetcode.cn/problems/binary-search/
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
vector<int> dp(cost.size());
dp[0] = cost[0];
dp[1] = cost[1];
for (int i = 2; i < cost.size(); i++) {
dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i];
}
return min(dp[cost.size() - 1], dp[cost.size() - 2]);
}
};
int main() {
int a[] = {
1, 100, 1, 1, 1, 100, 1, 1, 100, 1};
vector<int> cost(a, a + sizeof(a) / sizeof(int));
Solution solution;
cout << solution.minCostClimbingStairs(cost) << endl;
}
从代码中可以看出,其实就是定义个main函数,构造个输入用例,然后定义一个solution变量,调用minCostClimbingStairs函数就可以了。
class Person{
private:
char name[10];
char addr[20];
char phone[11];
public:
void initData(){
...};
char* getAddr(){
...};
char* getPhone(){
...};
}
对于类中的private
和public
区域,其中private区域中的数据定义对外部程序是隐蔽的,public区域中的函数是提供给外部访问类功能的借口。程序中的任何函数只有通过public中的函数才能够修改或者查看类中的private属性。