merge两个有序数组 & 查找一个有序数组中指定元素
来源:互联网 发布:人工智能 数据挖掘 编辑:程序博客网 时间:2024/05/17 22:13
20. 合并有序数组。给定升序排列的两个数组array1和array2,要求将array2合并到array1中,并保持结果有序是升序的。假设
array1有足够的空间容纳array2.起初array1和array2的元素各有m和n个。
solution:
可以直接使用归并排序中的merge()对有序数组直接合并。但是由于不能使用额外的存储,不像归并排序那样,所以插入一个元素
可能会导致元素的搬动,为了减少元素搬动,可以从array1的右边开始插入元素,也就是array1[n+m-1]。
由于两个数组都是升序的,那么从两个数组最大的元素开始比较,也就是array1[m-1]和array2[n-1]。将大的一个加入到array1[n+m-1]。
换句话说,新数组的最后一个元素要么来自array1[m-1],要么是array2[n-1]。当完成插入后,被插入的指针左移一步。这样可以保证没
有元素在插入之前被flush掉。插入之后再被其他元素flush掉是没有问题的。
算法的代码实现如下:
public class question20 {
void merge2SortedArrays(int[] array1, int[] array2){
int m=array1.length;
int n=array2.length;
while(n>0){
if(m<0 || array1[m-1] < array2[n-1])
//当数组1取完了所有的元素,或者当前1数组的元素比2数组的元素小,由于是升序排序并且是由右边插入元素
//那么我们取数组2的元素插入。之后数组2的指针左移一步
array1[n+m-1]=array2[n--];
else
//数组1插入到n+m-1的位置,m向左移动一步
array1[n+m-1]=array1[m--];
}
}
}
21. 区间搜索。给定一个升序的数组,这个数组中可能含有相同的元素,并且给定一个目标值。要求找出目标值在数组中的开始下标以及
终止下标。如果这个数组不含有该目标值,就返回[-1,-1]。要求算法的时间复杂度是O(logn),其中n是数组长度。
比如,array={1,3,4,4,5},target=4,那么返回[2,3]。如果target是8,那么返回[-1,-1]。
solution:
借鉴二分查找的算法思想。分两步进行,第一步为了找到起点,先找到比目标值下标最靠近的目标元素,也就是左邻居。比如上面的左邻
居是3。那么开始下标就是3的下标++。第二步和第一步类似,为了找到终止下标,要找到右邻居,比如上面的5,那么就是5的下标--。
由于是2步的二分查找,算法的时间复杂度仍然是O(logn)。算法的代码实现如下:
public class question21 {
int[] searchRange(int[] array, int target) {
int[] range = { -1, -1 };
// 注意left是数组的第一个下标-1,因为左邻居可能不存在,比如{1,1,3,5}找1,那么左邻居下标是-1,起点下标就是-1+1=0
int left = -1;
// 注意right是数组的最后一个下标+1,因为右邻居可能不存在,比如{1,2,4,4},找4,那么右邻居的下标是4,4-1=3才是终止下标
int right = array.length;
int mid;// 二分查找的中间值
if (array[right - 1] < target)// 由于array是升序排列的,此时一定不存在数组中的target
return range;
// 搜索左邻居,使用二分查找
while (left < right) {
mid = (left + right) / 2;
if (array[mid] < target)
//
left = mid + 1;
else
right = mid;
}
if (array[left + 1] == target)// left是左邻居的下标
range[0] = left + 1;// left+1就是目标值的起始下标
else
// 找不到左邻居,那么target一定不出现在数组中,直接返回range
return range;
// 搜索右邻居
// 先将right回朔到原先的位置,保留上面计算出来的left.
right = array.length;
left++;
// 在起始下标left+1和right之间进行二分查找
while (left < right) {
mid = (left + right) / 2;
if (array[mid] > target) {
right = mid;
} else
left = mid + 1;
}
range[1] = right - 1;// 终止下标是右邻居下标-1
return range;
}
}
22. 插入位置。给定一个升序排序的数组和一个目标值,返回目标值的下标。如果目标值不在数组里,那么返回这个目标值插入数组后的下标。
要求插入之后数组仍然保持有序。并且假定数组不存在重复元素。要求算法的时间复杂度是O(logn)
比如,array={1,2,4,5,6},target=3,则返回2。又如,array={1,2,3,4,5},target=4,那么返回3。
solution:
由于是升序排序的,只要找到第一个大于或者等于target的元素就行了。使用一般的二分查找算法就可以实现了。具体的代码如下:
public class question22 {
int toSearchInsert(int[] array, int target){
int left=0, right=array.length-1, mid;
while(left<=right){
mid=(left+right)/2;
if(array[mid]==target){
return mid;
}else if(array[mid]>target){
right=mid-1;
}else{
left=mid+1;
}
}
return left;
}
}
array1有足够的空间容纳array2.起初array1和array2的元素各有m和n个。
solution:
可以直接使用归并排序中的merge()对有序数组直接合并。但是由于不能使用额外的存储,不像归并排序那样,所以插入一个元素
可能会导致元素的搬动,为了减少元素搬动,可以从array1的右边开始插入元素,也就是array1[n+m-1]。
由于两个数组都是升序的,那么从两个数组最大的元素开始比较,也就是array1[m-1]和array2[n-1]。将大的一个加入到array1[n+m-1]。
换句话说,新数组的最后一个元素要么来自array1[m-1],要么是array2[n-1]。当完成插入后,被插入的指针左移一步。这样可以保证没
有元素在插入之前被flush掉。插入之后再被其他元素flush掉是没有问题的。
算法的代码实现如下:
public class question20 {
void merge2SortedArrays(int[] array1, int[] array2){
int m=array1.length;
int n=array2.length;
while(n>0){
if(m<0 || array1[m-1] < array2[n-1])
//当数组1取完了所有的元素,或者当前1数组的元素比2数组的元素小,由于是升序排序并且是由右边插入元素
//那么我们取数组2的元素插入。之后数组2的指针左移一步
array1[n+m-1]=array2[n--];
else
//数组1插入到n+m-1的位置,m向左移动一步
array1[n+m-1]=array1[m--];
}
}
}
21. 区间搜索。给定一个升序的数组,这个数组中可能含有相同的元素,并且给定一个目标值。要求找出目标值在数组中的开始下标以及
终止下标。如果这个数组不含有该目标值,就返回[-1,-1]。要求算法的时间复杂度是O(logn),其中n是数组长度。
比如,array={1,3,4,4,5},target=4,那么返回[2,3]。如果target是8,那么返回[-1,-1]。
solution:
借鉴二分查找的算法思想。分两步进行,第一步为了找到起点,先找到比目标值下标最靠近的目标元素,也就是左邻居。比如上面的左邻
居是3。那么开始下标就是3的下标++。第二步和第一步类似,为了找到终止下标,要找到右邻居,比如上面的5,那么就是5的下标--。
由于是2步的二分查找,算法的时间复杂度仍然是O(logn)。算法的代码实现如下:
public class question21 {
int[] searchRange(int[] array, int target) {
int[] range = { -1, -1 };
// 注意left是数组的第一个下标-1,因为左邻居可能不存在,比如{1,1,3,5}找1,那么左邻居下标是-1,起点下标就是-1+1=0
int left = -1;
// 注意right是数组的最后一个下标+1,因为右邻居可能不存在,比如{1,2,4,4},找4,那么右邻居的下标是4,4-1=3才是终止下标
int right = array.length;
int mid;// 二分查找的中间值
if (array[right - 1] < target)// 由于array是升序排列的,此时一定不存在数组中的target
return range;
// 搜索左邻居,使用二分查找
while (left < right) {
mid = (left + right) / 2;
if (array[mid] < target)
//
left = mid + 1;
else
right = mid;
}
if (array[left + 1] == target)// left是左邻居的下标
range[0] = left + 1;// left+1就是目标值的起始下标
else
// 找不到左邻居,那么target一定不出现在数组中,直接返回range
return range;
// 搜索右邻居
// 先将right回朔到原先的位置,保留上面计算出来的left.
right = array.length;
left++;
// 在起始下标left+1和right之间进行二分查找
while (left < right) {
mid = (left + right) / 2;
if (array[mid] > target) {
right = mid;
} else
left = mid + 1;
}
range[1] = right - 1;// 终止下标是右邻居下标-1
return range;
}
}
22. 插入位置。给定一个升序排序的数组和一个目标值,返回目标值的下标。如果目标值不在数组里,那么返回这个目标值插入数组后的下标。
要求插入之后数组仍然保持有序。并且假定数组不存在重复元素。要求算法的时间复杂度是O(logn)
比如,array={1,2,4,5,6},target=3,则返回2。又如,array={1,2,3,4,5},target=4,那么返回3。
solution:
由于是升序排序的,只要找到第一个大于或者等于target的元素就行了。使用一般的二分查找算法就可以实现了。具体的代码如下:
public class question22 {
int toSearchInsert(int[] array, int target){
int left=0, right=array.length-1, mid;
while(left<=right){
mid=(left+right)/2;
if(array[mid]==target){
return mid;
}else if(array[mid]>target){
right=mid-1;
}else{
left=mid+1;
}
}
return left;
}
}
0 0
- merge两个有序数组 & 查找一个有序数组中指定元素
- 找出有序元素数组中指定元素出现的次数
- 查找数组中指定元素
- 有序二维数组查找元素
- 二分法查找有序数组元素
- 有序二维数组查找元素
- Python 查找有序列表中指定元素所在位置
- Merge Sorted Array 合并两个有序数组
- Merge Sorted Array -- 合并两个有序数组
- Merge Sorted Array合并两个有序数组
- merge两个有序数组,合并之后仍保持有序
- 将两个有序数组归并为一个有序数组
- java将两个有序数组合并成一个有序数组
- 两个有序数组合并为一个有序数组
- 两个有序数组合并为一个有序数组
- 两个有序数组合并为一个有序数组
- 两个有序数组合并为一个有序数组
- 两个有序数组合并成一个有序数组
- epoll使用说明
- 腾讯公司的几道历年面试题精选
- VELT-0.1.3开发: 预处理器
- hehe
- SQL SERVER 2005 请求失败或服务未及时响应
- merge两个有序数组 & 查找一个有序数组中指定元素
- python int() 和long()函数 转换 字符串类型的浮点数
- (ios)xml数据交换格式
- Android传感器-开发指南
- Arrays 的copyOf()
- 黑马程序员-ios学习笔记 C语言基础语法
- Objective - C基础: 第五天 - 2.多个对象之间的内存管理
- wget使用技巧
- Activiti 5.17 一行代码验证并启动引擎