注1:原文来自 CSDN博主 【趁着头发多我想做游戏】htt防和谐ps://blog.csdn.n防和谐et/weixin_37658157/article/details/88087867 转载请注明出处
知识点:
http://www.cnblogs.com/gavanwanggw/p/7307596.html
求链地址法的平均长度 ASL(包含查找成功和不成功) : https://blog.csdn.net/ecnuThomas/article/details/69666559
总结:
知识点:https://www.cnblogs.com/skywang12345/p/3596746.html
左右指针法(基准是每一趟结束时才移动的):设第一个元素为基准,首先从右往左扫描一个比基准小的,再从第二个元素开始从左往右扫描一个比基准大的,交换他们,重复这个过程直到碰头,最后把基准把碰头位置交换,此时基准已经在正确的位置,然后递归这个位置的左半部分和右半部分。
挖坑法(基准每一趟一开始就移动):设第一个元素为基准,首先从右往左扫描一个比基准小的,这个元素的位置定义为“坑”,把这个元素填充到基准位置,再从第二个元素开始从左往右扫描一个比基准大的,把这个元素填充到上一个“坑”位置,重复这个过程直到碰头,这个碰头位置也是一个“坑”,最后把基准的值填充到坑中,此时基准已经在正确的位置,然后递归这个位置的左半部分和右半部分。
注意挖坑法和左右指针法的第一趟排序结果不一定一样!因此没有符合的选项就要换另外一种方法来检验
挖坑法注意:若选择最左边的元素为枢纽,则要先走right指针,原因是:如5 3 4 6 7 8 10 11 12 选5为枢纽,若left先走,则要交换5和6,显然不符合
下面给出左右指针法的代码:
public static void QuickSort(int[] arr,int left,int right)
{
if(left>right)
return;
int temp = Partition(arr,left,right);//基准
QuickSort(arr, left, temp-1);
QuickSort(arr, temp+1, right);
}
//左右指针法
public static int Partition(int[] arr,int left,int right)
{
//默认基准index是最左边的那个
int i = left,j = right,index = left;
while(i<j)
{
while(i<j && arr[j]>=arr[index])
j--;
while(i<j && arr[i]<=arr[index])
i++;
if(i<j)
{
Swap(arr, i, j);
}
}
Swap(arr, j, index);
return j;
}
知识点:https://blog.csdn.net/qq_33243189/article/details/80222629
四种基本的遍历思想为:
前序遍历:根结点 —> 左子树 —> 右子树
中序遍历:左子树 —> 根结点 —> 右子树
后序遍历:左子树 —> 右子树 —> 根结点
层次遍历的步骤是:(相当于广度搜索,上面的都是深度搜索)
1.对于不为空的结点,先把该结点加入到队列中
2.从队头拿出结点,如果该结点的左右结点不为空,就分别把左右结点加入到队列中
3.重复 步骤 2 直到队列为空
感悟:这个前中后序指的是访问根节点的先后
知识点:https://www.cnblogs.com/zhaoshuai1215/p/3448154.html
算法思路(以从小到大排序为例):
1. 冒泡排序: 每个元素和其他元素比较,一旦比自己大,就交换,第一趟的最后一个元素一定是最大的,因此第二趟比较时不需要再比较最后的元素
2. 直接插入排序: 每个元素和左边所有的元素(从右往左)比较,一旦比自己大,就交换,直至找到比自己小的位置;
3. 希尔排序: 最小增量排序,增量公式:n = n / 3 + 1,按增量划分成(Length / 3+1)个分组,每个分组执行直接插入排序,直至增量减少到1;
4. 快速排序:
左右指针法(基准是每一趟结束时才移动的):设第一个元素为基准,首先从右往左扫描一个比基准小的,再从第二个元素开始从左往右扫描一个比基准大的,交换他们,重复这个过程直到碰头,最后把基准把碰头位置交换,此时基准已经在正确的位置,然后递归这个位置的左半部分和右半部分。
挖坑法(基准每一趟一开始就移动):设第一个元素为基准,首先从右往左扫描一个比基准小的,这个元素的位置定义为“坑”,把这个元素填充到基准位置,再从第二个元素开始从左往右扫描一个比基准大的,把这个元素填充到上一个“坑”位置,重复这个过程直到碰头,这个碰头位置也是一个“坑”,最后把基准的值填充到坑中,此时基准已经在正确的位置,然后递归这个位置的左半部分和右半部分。
设n是数据长度,k是寻找次数
每次二分 直到最后一次才找到 就会有 2^k = n / 2 得到 k = log2(n)+1
真题:
一个家庭有两个小孩,其中一个是女孩、另一个也是女孩的概率是 1/3
解析:
设事件A为两个孩子中有女孩,事件B为第二个孩子为女孩。
则
P(A)=1-1/4=3/4(即求至少有一个女孩的情况概率)
P(AB)=1/2*1/2=1/4(两个都是女孩的概率)
P(B|A)=P(AB)/P(A)=1/4 / 3/4 =1/3(条件概率)
另一种解法:两个小孩可能是 男男,男女,女男,女女
已知其中一个是女孩,也就是后三种情况中的一种,男女,女男,女女
只有最后一种情况另一个也是女孩。因此另一个也是女孩的概率是1/3
真题:
若有以下定义和赋值语句,则与&s[i][j]等价的是 *(p+i)+j
int s[2][3] = {0}, (*p)[3], i, j;
p = s;
i = j = 1;
解析:
int (*p)[3] 表示一个指针,指向一个含有三个元素的数组;
p=s,表示p指向了数组s的第一行,
p+1 表示现在指针指向了数组s的第二行;
*(p+1)表示数组s第二行第一个元素的地址;
*(p+1)+1 表示数组s第二行第二个元素的地址;
例题:若以{4,5,6,7,8}作为叶子结点的权值构造哈夫曼树,则其带权路径长度是()。
构造方法是每次取最小的两个数, 合并成一个数, 然后循环这种做法, 直到只剩一个点为止。构造的树是
所以带权路径长度是 (4+5)* 3 + (6+7+8) * 2 = 102
以下问题的通用答案:S=C(2n,n)-C(2n,n-1)
1.括号化问题。
矩阵链乘: P=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?(h(n)种)
2.出栈次序问题。
一个栈(无穷大)的进栈序列为1,2,3,..n,有多少个不同的出栈序列?
类似:有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?(将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈)
3.将多边行划分为三角形问题。
将一个凸多边形区域分成三角形区域的方法数?
类似:一位大城市的律师在她住所以北n个街区和以东n个街区处工作。每天她走2n个街区去上班。如果她从不穿越(但可以碰到)从家到办公室的对角线,那么有多少条可能的道路?
类似:在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数?
4.给顶节点组成二叉树的问题。
给定N个节点,能构成多少种不同的二叉树?
真题:
i的初始值为0,i++在两个线程里面分别执行100次,能得到最大值是 200 ,最小值是 2
解析:
i++只需要执行一条指令,并不能保证多个线程i++操作同一个i,可以得到正确的结果。
因为还有寄存器的因素,多个cpu对应多个寄存器。每次要先把i从内存复制到寄存器,
然后++,然后再把i复制到内存中,这需要至少3步。
根据异或运算特点:
1.异或满足交换律。
2.相同两个数异或为0。
3.0异或一个数为那个数本身。
如 1^ 2 ^ 1 = 1 ^ 1 ^ 2 = 0 ^ 2 = 2
public static int singleNumber(int[] A) {
int num = 0;
for(int i=0;i<A.length;i++){
num^=A[i];
}
return num;
}
知识点:https://blog.csdn.net/qq_35295155/article/details/78639997
public static void BubbleSort(int[] arr)
{
for(int i=0;i<arr.length;i++)//控制比较趟数
{
for(int j=0;j<arr.length-1-i;j++)//控制每一趟两两比较次数,每一趟排序完最后一个元素都是已经排好的,下一趟不需要再比较
{
if(arr[j]>arr[j+1])
{
Swap(arr, j, j+1);
}
}
}
}
public static void InsertSort(int[] arr)
{
for (int i = 1; i < arr.length; i++)
{
for (int j = i; j > 0; j--)
{
if(arr[j]<arr[j-1])
{
Swap(arr, j, j-1);
}
else
{
break;//由于每一趟结束,左部分是一个有序数组,一旦碰到比自己小的元素,则证明其他更小,所以可以跳出循环
}
}
}
}
public static void ShellSort(int[] arr)
{
//增量
int n = arr.length;
while(n>1)//增量不断减少,直至为1
{
n = n/3+1;
for (int i = 0; i < n; i++) {//一共分为了n/3+1个分组,如长度为5,则增量为2,共2组,可自行试验
//每个分组分别进行直接插入排序
for(int j = i+n; j < arr.length;j+=n)//从分组的第二个元素开始比较该元素左边的所有元素
{
for(int k = j;(k-n)>=0 && k > 0;k-=n)//注意比较的两个数的下标都要大于等于0
{
if(arr[k]<arr[k-n])
{
Swap(arr, k, k-n);
}
else
{
break;
}
}
}
}
}
}
public static void SelectSort(int[] arr)
{
for (int i = 0; i < arr.length; i++) {
int minIndex = i;
for (int j = i+1; j < arr.length; j++) {
if(arr[minIndex] > arr[j])
{
minIndex = j;
}
}
Swap(arr, minIndex, i);
}
}
public static void QuickSort(int[] arr,int left,int right)
{
if(left>right)
return;
int temp = Partition(arr,left,right);//基准
QuickSort(arr, left, temp-1);
QuickSort(arr, temp+1, right);
}
//左右指针法
public static int Partition(int[] arr,int left,int right)
{
//默认基准index是最左边的那个
int i = left,j = right,index = left;
while(i<j)
{
while(i<j && arr[j]>=arr[index])
j--;
while(i<j && arr[i]<=arr[index])
i++;
if(i<j)
{
Swap(arr, i, j);
}
}
Swap(arr, j, index);
return j;
}
int BinSearch(SeqList *R,int n,KeyType K)
{
//在有序表R[0..n-1]中进行二分查找,成功时返回结点的位置,失败时返回-1
int low=0,high=n-1,mid; //置当前查找区间上、下界的初值
while(low<=high)
{
if(R[low].key==K)
return low;
if(R[high].key==k)
return high; //当前查找区间R[low..high]非空
mid=low+(high-low)/2;
/*使用(low+high)/2会有整数溢出的问题
(问题会出现在当low+high的结果大于表达式结果类型所能表示的最大值时,
这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)
不存在这个问题*/
if(R[mid].key==K)
return mid; //查找成功返回
if(R[mid].key<K)
low=mid+1; //继续在R[mid+1..high]中查找
else
high=mid-1; //继续在R[low..mid-1]中查找
}
return -1;//当low>high时表示所查找区间内没有结果,查找失败
}
原文来自 CSDN博主 【趁着头发多我想做游戏】htt防和谐ps://blog.csdn.n防和谐et/weixin_37658157/article/details/88087867 转载请注明出处