算法-链表
1. 双指针技巧
1.1 反转链表🔥
- 循环版本
1 | package main |
算法-数组
1. 数组中重复的数字(简单)
头脑风暴: 临时数组++
1
2
3
4
5
6
7
8
9
10
11
12func findRepeatNumber(nums []int) int {
arr := make([]int, len(nums), len(nums))
for i := 0; i < len(nums); i++{
arr[nums[i]]++ // 题目说明, <n, 不会越界
if arr[nums[i]] > 1{
return nums[i]
}
}
return 0
}
2. 合并两个有序数组
1 | func merge(nums1 []int, m int, nums2 []int, n int) { |
算法复杂度的理解
复杂度分析主要从「时间」和「空间」两个维度来进行分析。
时间维度顾名思义就是算法需要消耗的时间,「时间复杂度」是常用的分析单位。
空间维度代表算法需要占用的内存空间,我们通常用「空间复杂度」来分析。
markdown写作typora的配置
mac上写作markdown,个人感觉目前还没有比typora更优秀的工具(obsidian不服)。
yaml语言教程
linux信号和锁
1. 信号
1.1 产生信号的条件
- 用户在终端按下某些键时,终端驱动程序会发送信号给前台进程,例如Ctrl-C产生
SIGINT
信号,Ctrl-\产生SIGQUIT
信号,Ctrl-Z产生SIGTSTP
信号。 - 硬件异常产生信号,这些条件由硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释为
SIGFPE
信号发送给进程。再比如当前进程访问了非法内存地址,,MMU会产生异常,内核将这个异常解释为SIGSEGV
信号发送给进程。 - 一个进程调用
kill(2)
函数可以发送信号给另一个进程。 - 可以用
kill(1)
命令发送信号给某个进程,kill(1)
命令也是调用kill(2)
函数实现的,如果不明确指定信号则发送SIGTERM
信号,该信号的默认处理动作是终止进程。 - 当内核检测到某种软件条件发生时也可以通过信号通知进程,例如闹钟超时产生
SIGALRM
信号,向读端已关闭的管道写数据时产生SIGPIPE
信号。
makefile的选项CFLAGS、CPPFLAGS、LDFLAGS和LIBS的区别
先看一个例子:
1 | export CFLAGS="-I/root/ARM/opt/include" |
CFLAGS: 指定头文件(.h文件)的路径,如:CFLAGS=-I/usr/include -I/path/include。同样地,安装一个包时会在安装路径下建立一个include目录,当安装过程中出现问题时,试着把以前安装的包的include目录加入到该变量中来。
LDFLAGS:gcc 等编译器会用到的一些优化参数,也可以在里面指定库文件的位置。用法:LDFLAGS=-L/usr/lib -L/path/to/your/lib。每安装一个包都几乎一定的会在安装目录里建立一个lib目录。如果明明安装了某个包,而安装另一个包时,它愣是说找不到,可以抒那个包的lib路径加入的LDFALGS中试一下。
LIBS:告诉链接器要链接哪些库文件,如LIBS = -lpthread -liconv
交叉编译arm-transmission-2.94
arm交叉编译器的区别
为什么要用交叉编译器?
交叉编译通俗地讲就是在一种平台上编译出能运行在体系结构不同的另一种平台上的程序,比如在PC平台(X86 CPU)上编译出能运行在以ARM为内核的CPU平台上的程序,编译得到的程序在X86 CPU平台上是不能运行的,必须放到ARM CPU平台上才能运行,虽然两个平台用的都是Linux系统。
交叉编译工具链是一个由编译器、连接器和解释器组成的综合开发环境,交叉编译工具链主要由binutils、gcc和glibc三个部分组成。有时出于减小 libc 库大小的考虑,也可以用别的 c 库来代替 glibc,例如 uClibc、dietlibc 和 newlib。
建立交叉编译工具链是一个相当复杂的过程,如果不想自己经历复杂繁琐的编译过程,网上有一些编译好的可用的交叉编译工具链可以下载,但就以学习为目的来说读者有必要学习自己制作一个交叉编译工具链(目前来看,对于初学者没有太大必要自己交叉编译一个工具链)。