本篇若要说难点,就是时间复杂度的把控,还有什么样的解法容易让大家看懂理解
JZ53 数字在升序数组中出现的次数
描述
给定一个长度为 n 的非降序数组和一个非负数整数 k ,要求统计 k 在数组中出现的次数
数据范围:0 \le n \le 1000 , 0 \le k \le 1000≤n≤1000,0≤k≤100,数组中每个元素的值满足 0 \le val \le 1000≤val≤100
要求:空间复杂度 O(1),时间复杂度 O(logn)
思路(二分法):由于所需时间复杂度为O(logn),所以可以先通过二分法找到所给的k值,并拿到k值的下标,因为是有序数组,所以由此展开——用left和right分别向左和向右遍历,若与k值相等,则给计数器+1,最后返回计数器即可;
//计数器
private int count = 0;
public int GetNumberOfK(int [] array , int k) {
//由于时间复杂度为O(logn),所以要利用二分查找先找到这个数
int len = array.length;
int left = 0;
int right = len - 1;
int keyIndex = binarySearch(array, left, right, k);
if(count == -1){
return 0;
}
//因为有序,所以分别向两边扩展找相同的元素,找到了,计数就加1
//左扩展
left = keyIndex - 1;
while(left >= 0 && array[left] == k){
count++;
left--;
}
//右扩展
right = keyIndex + 1;
while(right < len && array[right] == k){
count++;
right++;
}
return count;
}
//二分查找
private int binarySearch(int[] array, int left, int right, int k){
while(left <= right){
int mid = (left + right) / 2;
if(k < array[mid]){
right = mid - 1;
}else if(array[mid] < k){
left = mid + 1;
}else{
count++;
return mid;
}
}
return -1;
}
JZ4 二维数组中的查找
描述
在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
[
[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]
]
给定 target = 7,返回 true。
给定 target = 3,返回 false。
数据范围:矩阵的长宽满足 0 \le n,m \le 5000≤n,m≤500 , 矩阵中的值满足 0 \le val \le 10^90≤val≤109
进阶:空间复杂度 O(1),时间复杂度 O(n+m)
思路(这题其实非常简单,但此题的标出的难度却是中等,通过率只有百分之二十几?想必大多数人都是因为时间复杂度超过了O(n + m)):为什么简单?二维数组,对每一行进行二分查找就ok~
public boolean Find(int target, int [][] array) {
//每一行进行二分查找
for(int i = 0; i < array.length; i++){
boolean flay = binarySearch(target, array[i]);
if(flay){
return true;
}
}
return false;
}
public boolean binarySearch(int target, int[] array){
int left = 0;
int right = array.length - 1;
while(left <= right){
int mid = (left + right) / 2;
if(target < array[mid]){
right = mid - 1;
}else if(target > array[mid]){
left = mid + 1;
}else{
return true;
}
}
return false;
}
JZ11 旋转数组的最小数字
描述
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
数据范围:1 \le n \le 100001≤n≤10000,数组中任意元素的值: 0 \le val \le 100000≤val≤10000
要求:空间复杂度:O(1) ,时间复杂度:O(logn)
思路(二分法):因为数组为非降序数组,所以可以通过二分法,进行循环即可,但要注意以下情况:当mid指向元素大于right指向元素时,说明目标值一定在mid指向的右边;当mid指向元素小于right指向元素时,说明一定在mid指向的左边;若mid指向元素等于right指向元素时,不确定,可以用right缩小范围继续比较;
public int minNumberInRotateArray(int [] array) {
int left = 0;
int right = array.length - 1;
while(left < right){
int mid = (left + right) / 2;
//若中间值大于最右边,说明目标在中间值右边
if(array[mid] > array[right]){
left = mid + 1;
}
//此时不确定,比如 1 1 1 0 1,所以继续缩小范围
else if(array[mid] == array[right]){
right--;
}
//不在右边就在左边
else{
right = mid;
}
}
return array[left];
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/129870.html