Ref:
https://blog.csdn.net/weixin_30906671/article/details/97901352(数组指针,指针数组,多维数组<--->指针)
https://blog.csdn.net/iu_81/article/details/1782642(二维数组和指针)
一维数组和指针
int a[10];
int *p;
p = &a[0]; <==> p = a; <==> int *p = &a[0]; <==> int *p = a; //把a数组的首元素的地址赋值给指针变量p
p+1; //指向数组的下一个元素,p+1的地址实际是p+1*(sizeof(int));.注意a是数组元素的首地址,是一个指针常量
p+i <==>a+i <==>&a[i]
*(p+i) <==>*(a+i) <==>a[i]
*p++ <==> *(p++); //先拿到*p,然后再p=p+1;
(*p)++;//p指向的元素值加1,是元素值加1,内容加1,不是指针加1
二维数组和指针
二维数组:要用指针处理二维数组,首先要解决从存储的角度对二维数组的认识问题。我们知道,一个二维数组在计算机中存储时,是按照先行后列的顺序依次存储的,当把每一行看作一个整体,即视为一个大的数组元素时,这个存储的二维数组也就变成了一个一维数组了。而每个大数组元素对应二维数组的一行,我们就称之为行数组元素,显然每个行数组元素都是一个一维数组
2.用二维数组名作地址表示数组元素。
a<==> a[0];//注意是a[0],不是&a[0];代表是第0行的首地址
a+1 <==>a[1];//代表第1行的首地址
a[0],a[1],a[2]都是一维数组的数组名(相当于上例一维数组中p),又是一维数组a[0]中第0列元素的地址,即&a[0][0], a[1]<==>&a[1][0]; a[2]<==>&a[2][0]
对于二维数组a,其a[0]数组由a指向,a[1]数组则由a+1指向,a[2]数组由a+2指向,以此类推。因此,*a与a[0]等价、*(a+1)与a[1]等价、*(a+2)与a[2]等价,┅,即对于a[i]数组,由*(a+i)指向。由此,对于数组元素a[i][j],用数组名a的表示形式为:*(*(a+i)+j)指向该元素的指针为:*(a+i)+j数组名虽然是数组的地址,但它和指向数组的指针变量不完全相同。指针变量的值可以改变,即它可以随时指向不同的数组或同类型变量,而数组名自它定义时起就确定下来,不能通过赋值的方式使该数组名指向另外一个数组(二维数组不能作为右值)。
剑指Offer(一):二维数组中的查找
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。(使用二分查找:找到中间的,也就是右上角或左下角)
剑指Offer(六):旋转数组的最小数字
剑指Offer(十三):调整数组顺序使奇数位于偶数前面
1,插排
2,冒泡排
3,快排不稳定,不适用于这道题
4,新建一个数组,空间换时间
1.插排
if(array==null){
return;
}
//原书中的方法 类似于快排
/*int i=0;
int j=array.length-1;
while(i<j){
while(i<j&&array[i]%2==1){
i++;
}
while(i<j&&array[j]%2==0){
j--;
}
int temp=array[j];
array[j]=array[i];
array[i]=temp;
}*/
//由于要保证稳定即证奇数和奇数,偶数和偶数之间的相对位置不变 使用插入排序思想
for(int i=0;i<array.length;i++){
//int temp=array[i];
if(array[i]%2==1){
int temp=array[i];
int j=i-1;
while(j>=0&&array[j]%2==0){
array[j+1]=array[j];
j--;
}
array[j+1]=temp;
}
}
2.
剑指Offer(二十八):数组中出现次数超过一半的数字
剑指Offer(三十):连续子数组的最大和
剑指Offer(三十二):把数组排成最小的数
剑指Offer(三十五):数组中的逆序对
剑指Offer(三十七):数字在排序数组中出现的次数
剑指Offer(四十):数组中只出现一次的数字
剑指Offer(五十):数组中重复的数字
剑指Offer(五十一):构建乘积数组