理论小笔记

平常一般用markdown写博客,最近翻出这篇古早博客就懒得改了,凑活着看吧QAQ。

看这里看这里!

 

关于几个类型的范围

 

       int                             -2147483647-2147483648                                             -2^31~2^31-1

       long                           -2147483647~2147483648                                             -2^31~2^31-1  (和int相等)

       unsigned long long     0~18446744073709551615                                              0~2^64-1

       unsigned int              0~4294967295                                                                 0~2^32-1

       unsigned long            0~4294967295                                                                 0~2^32-1

       long long的最大值:   -9223372036854775808 ~ 9223372036854775807      -2^63,2^63-1

 


 

 

0x3f3f3f3f与0x7fffffff的意义

 

          当使用min等函数的时候,会需要定义无穷大。一般会有两个选择:0x7fffffff和0x3f3f3f3f

 

 

- 0x7fffffff

          首先了解数字的含义,"0x"是一个前缀,表示十六进制。

          而"7"在二进制中是7的二进制码为 0111,f是指1111。

          这样, 0x7FFFFFFF 的二进制表示就是除了符号位是 0表示正数,其余都是1。

          对于int而言,0x7fffffff是最大的数值。

          所以可以把需要比较的无穷大设为0x7fffffff再进行比较。

 

- 0x3f3f3f3f

          在实际写代码的时候,有的时候并不会出现接近于2^31这样的数值,因此可以把无穷大设得小一点,一般设为0x3f3f3f3f。

          0x3f3f3f3f的数值为1061109567,它的两倍也只有2122219134,不会溢出。

          这样就有一个好处,当两个无穷大相加的时候可以使int型整数不溢出,并使数值仍为无穷大。

          而使用0x3f3f3f3f在对于数组定义的时候也比较方便,一般数组批量赋值时会使用memset函数,如果想将一个数组全部定义为"无穷大"的0x3f3f3f3f,因为memset函数是对字节进行操作,而0x3f3f3f3f的每个字节都是0x3f,所以可以直接定义为

memset(数组名,0x3f,sizeof(数组名));

          特别的,浮点数数组如double,float初始化为正无穷应使用

 

memeset(数组名,127,sizeof(数组名));

 

 

 


 

数组初始化(memset的使用)

 

          同上,数组初始化可以使用memset快速赋值。需要加上#include<string.h>的头文件

               例:

memset(arr,0,sizeof(arr));//将arr数组全部赋值为0

 

                这是一般的数组赋值,char型的二维数组也可以使用memset赋值,但是!不能用于int型二维数组的赋值。

                为什么?

                就像上面说过的,memset中输入的1,相当于转换成了0x01010101,转换成十进制就是16843009,而全赋值为0是允许的。

 

 


 

 

如何在O(n)时间复杂度中查找第k大元素

 

            比如,4, 2, 5, 12, 3 这样一组数据,第 3 大元素就是 4。

    我们选择数组区间 A[0…n-1] 的最后一个元素 A[n-1] 作为 pivot,对数组 A[0…n-1] 原地分区,这样数组就分成了三部分,A[0…p-1]、A[p]、A[p+1…n-1]。

    如果 p+1=K,那 A[p] 就是要求解的元素;如果 K>p+1, 说明第 K 大元素出现在 A[p+1…n-1] 区间,我们再按照上面的思路递归地在 A[p+1…n-1] 这个区间内查找。同理,如果 K<p+1,那我们就在 A[0…p-1] 区间查找。

             我们再来看,为什么上述解决思路的时间复杂度是 O(n)?

             第一次分区查找,我们需要对大小为 n 的数组执行分区操作,需要遍历 n 个元素。第二次分区查找,我们只需要对大小为 n/2 的数组执行分区操作,需要遍历 n/2 个元素。依次类推,分区遍历元素的个数分别为、n/2、n/4、n/8、n/16.……直到区间缩小为 1。

             如果我们把每次分区遍历的元素个数加起来,就是:n+n/2+n/4+n/8+…+1。这是一个等比数列求和,最后的和等于 2n-1。所以,上述解决思路的时间复杂度就为 O(n)。

 


 

附录:

进制代称

H(Hexadecimal)——16进制

D(Decimal)——10进制

O(Octonary)——8进制

B(Binary)——2进制

 

占位符类型

   %c ASCII 字符

   %f 浮点数

   %p 指针

   %u 无符号十进制整数(unsigned int)

   %s 字符串

   %d 整数转成十进位

   %o 整数转成八进位

   %x 整数转成小写十六进位

   %X 整数转成大写十六进位

   %e 浮点数、e-记数法

   %g 自动舍去小数点后多余0

   %G 根据数值不同自动选择%f或%e

   %i 有符号十进制数(与%d相同)

 

时间复杂度与空间复杂度

排序法 最差时间分析 平均时间复杂度 稳定度 空间复杂度
冒泡排序 O(n²) O(n²) 稳定 O(1)
快速排序 O(n²) O(n*log2n) 不稳定 O(log2n)~O(n)
选择排序 O(n²) O(n²) 不稳定 O(1)
二叉树排序 O(n²) O(n*log2n) 不一定 O(n)
插入排序 O(n²) O(n²) 稳定 O(1)
堆排序 O(n*log2n) O(n*log2n) 不稳定 O(1)
希尔排序 O(n^1.5)

O(n^1.5)

不稳定

O(1)

计数排序 O(n+k) O(n+k) 稳定

O(n+k)

基数排序 O(nk) O(nk)(k为维度) 稳定

O(n+k)

归并排序 O(n*log2n) O(n*log2n) 稳定

O(n)

 

杂烩

 

1 Byte(字节)=8 bits,TB>GB>MB>KB>Byte

 

常见的面向过程高级语言: C语言、Fortran语言

常见的低级语言:汇编

高级语言与低级语言的区别:高级语言更易移植,需要编译运行,低级语言(汇编)常数极小,运行速度快

 

Catalan数 通项公式:h(n)=C[n,2n]/(n+1)

第一类stirling数 递推公式:S(n, k)= (n - 1) * S(n- 1, k) + S(n - 1, k - 1)

第二类stirling数 递推公式:S(n, k)=k* S(n- 1, k) + S(n - 1, k - 1)

Bell数 通项公式

 

任意二叉树,叶子节点数是度为2点节点数数量+1

 

中国获图灵奖的人物:姚期智

 

 

 

 

 

 

posted @ 2020-04-12 12:02  青鸢挽歌  阅读(212)  评论(1编辑  收藏  举报
浏览器标题切换
浏览器标题切换end