线性表使具有相同特征数据元素的一个有限序列,其中所含元素的个数是线性表的长度。
从语言实现的角度
顺序表有两种基本实现方式,一体式和分离式。
一体式结构,存储表信息的单元与元素存储区以连续的方式安排在一块存储区里,两部分数据的整体形成一个完整的顺序表对象。
分离式结构,表对象里只保存与整个表有关的信息(即容器和元素个数),实际数据元素存放在另一个独立的元素存储区里,通过链接与基本表对象关联。
从存储的角度
分为顺序型和链表型。
顺序型是将数据存放在固定的区间内,此时访问元素的效率很高,但删除和增加元素代价较大,如果要扩容只能整体搬迁。
链表型是元素之间是通过地址依次连结的,因此访问时必须从头开始逐步向后找,访问效率低,而删除和增加元素很方便,不需考虑扩容问题。
从访问限制的角度
栈和队列称为访问受限的线性表,插入和删除受到限制,只能在固定的位置进行。
从扩容的角度
链表、树、图扩容最灵活。数组最受限制。
数组时元素一个紧密在一起的序列,相互之间不需要记录彼此关系就能访问。
数组用索引的数字来表示每一项数据在数组中的位置,且在大多数编程语言中,索引是从0算起的。
int[] arr=new int[10];
int[] arr={2,5,0,4,6};
/**
* @param size 已经存放的元素个数
* @param key 待查找的元素
*/
public static int findByElement(int[] arr,int size,int key){
for(int i=0;i<size;i++){
if(arr[i]==key)
return i;
}
return -1;
}
将给定的元素插入到有序数组的对应位置中,可以先找位置,再将其后元素整体右移,最后插入到空位置上。
/**
* @param arr
* @param size 数组已经存储的元素数量,从1开始编号
* @param element 待插入的元素
* @return
*/
public static int addByElementSequence(int[] arr,int size,int element){
//size是从1开始编号,当size>=arr.length时,表示数组已满,不能再往里面添加元素
if(size>=arr.length)
return -1;
//问题1:这里index=0或index=size-1?index需要从size开始匹配找到要插入的位置
int index=size;
//问题2:这里i
for(int i=0;i<size;i++){
if(element<arr[i]){
index=i;
break;
}
}
//元素后移,问题3:这里j=size-1可以吗?从size开始,确保参与后移的元素范围是从index到size
for(int j=size;j>index;j--){
arr[j]=arr[j-1];//index下标开始的元素后移一个位置
}
arr[index]=element;//插入元素
return index;
}
先查是否存在元素,存在再删除元素
/**
* 遍历数组,如果发现目标元素,则将其删除,
* 数组的删除就是从目标元素开始,用后续元素依次覆盖前继元素
*
* @param arr 数组
* @param size 数组中的元素个数
* @param key 要删除的目标值
*/
public int removeByElement(int[] arr,int size,int key){
int index=-1;
for(int i=0;i<size;i++){
if(arr[i]==key){
index=i;
break;
}
}
if(index!=-1){
for(int i=index+1;i<size;i++)
arr[i-1]=arr[i];
size--;
}
return size;
}
896. 单调数列
public boolean isMonotonic(int[] nums){
return isSorted(nums,true)||isSorted(nums,false);
}
public boolean isSorted(int[] nums,boolean increasing){
int n=nums.length;
for(int i=0;i<n-1;++i){
if(increasing){
if(nums[i]>nums[i+1]){
return false;
}
}else{
if(nums[i]<nums[i+1]){
return false;
}
}
}
return true;
}
直接遍历数组,判断相邻元素是递增还是递减的。
public boolean isMonotonic2(int[] nums){
boolean inc=true,dec=true;
int n=nums.length;
for(int i=0;i<n-1;++i){
if(nums[i]>nums[i+1]){
inc=false;
}
if(nums[i]<nums[i+1]){
dec=false;
}
}
return inc||dec;
}
35. 搜索插入位置
public int searchInsert(int[] nums,int target){
int n=nums.length;
int left=0,right=n-1,ans=n;
while(left<=right){
int mid=((right-left)>>1)+left;
if(target<=nums[mid]){
ans=mid;
right=mid-1;
}else{
left=mid+1;
}
}
return ans;
}
88. 合并两个有序数组
public void merge(int[] nums1,int nums1_len,int[] nums2,int nums2_len){
int i=nums1_len+nums2_len-1;
int len1=nums1_len-1,len2=nums2_len-1;
while(len1>=0&&len2>=0){
if(nums1[len1]<=nums2[len2])
nums1[i--]=nums2[len2--];
else if(nums1[len1]>nums2[len2])
nums1[i--]=nums1[len1--];
}
//假如A或B数组还有剩余
while(len2!=-1)
num1[i--]=num2[len2--];
while(len1!=-1)
num1[i--]=num2[len1--];
}
public int[] mergeArrays(int[][] array){
int arrNums=array.length,arrLen;
if(arrNums==0){
return new int[0];
}
//数组长度校验
arrLen=array[0].length;
for(int i=1;i<arrNums;i++){
if(arrLen!=array[i].length){
return new int[0];
}
}
//开辟新空间
int[] result=new int[arrNums*arrLen];
//将各个数组依次合并到一起
for(int i=0;i<arrNums;i++){
for(int j=0;j<arrLen;j++){
result[i*srrLen+j]=array[i][j];
}
}
Arrays.sort(result);
return result;
}