JZ53 数字在升序数组中出现的次数
简单 通过率:33.35% 时间限制:1秒 空间限制:256M
知识点数组二分
描述
给定一个长度为 n 的非降序数组和一个非负数整数 k ,要求统计 k 在数组中出现的次数
数据范围:0≤n≤1000,0≤k≤100,数组中每个元素的值满足 0≤val≤100
要求:空间复杂度 O(1),时间复杂度 O(logn)
示例1
输入:
[1,2,3,3,3,3,4,5],3
返回值:
4
示例2
输入:
[1,3,4,5],6
返回值:
0
第一种方法:k + 0.5 和 k - 0.5
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
return BinarySearch(data, k + 0.5) - BinarySearch(data, k - 0.5);
}
int BinarySearch(vector<int>& nums, float target) {
int mid;
int low = 0;
int high = nums.size() - 1;
while (low <= high) {
mid = (low + high) / 2;
if (nums[mid] < target) {
low = mid + 1;
} else if (nums[mid] > target) {
high = mid - 1;
}
}
return low;
}
};
第二种方法:分别找到最左边的元素和最右边的元素
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int len = data.size();
if (len == 0) {
return 0;
}
int left = search_left(data, k);
int right = search_right(data, k);
if (left == -1 && right == -1) {
return 0;
} else {
return right - left + 1;
}
}
int search_left(vector<int> arr, int k) {
int mid;
int low = 0;
int high = arr.size() - 1;
while (low < high) {
mid = (low + high) / 2;
if (arr[mid] == k) {
high = mid;
} else if (arr[mid] < k) {
low = mid + 1;
} else if (arr[mid] > k) {
high = mid;
}
}
if(arr[low] == k) {
return low;
} else {
return -1;
}
}
int search_right(vector<int> arr, int k) {
int mid;
int low = 0;
int high = arr.size() - 1;
while (low < high) {
mid = (low + high + 1) / 2;
if (arr[mid] == k) {
low = mid;
} else if (arr[mid] < k) {
low = mid;
} else if (arr[mid] > k){
high = mid - 1;
}
}
if(arr[low] == k) {
return low;
} else {
return -1;
}
}
};
JZ4 二维数组中的查找
中等 通过率:26.73% 时间限制:1秒 空间限制:256M
知识点数组
描述
在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
[
[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]
]
给定 target = 7,返回 true。
给定 target = 3,返回 false。
数据范围:矩阵的长宽满足 0≤n,m≤500 , 矩阵中的值满足 0≤val≤109
进阶:空间复杂度 O(1) ,时间复杂度 O(n+m)
示例1
输入:
7,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
返回值:
true
说明:
存在7,返回true
示例2
输入:
1,[[2]]
返回值:
false
示例3
输入:
3,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
返回值:
false
说明:
不存在3,返回false
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
if ( array.empty() ) {
return false;
}
// 规律:
// 左下角的元素:大于它上边的元素,小于它右边的元素。
// 右上角的元素:大于它左边的元素,小于它下边的元素。
// 方法:从左下角元素开始,或者从右上角元素开始。
// 这里采用从右上角开始的方法。
int row = 0;
int col = array[0].size() - 1;
// array.size() 表示二维数组的行数(有几行,一维数组的数量)
// array[0].size() 表示二维数组的列数(有几列,一维数组的长度)
while ( row <= array.size() - 1 && col >= 0 ) {
if ( array[row][col] == target ) {
return true;
} else if ( array[row][col] < target ) {
row++;
} else if ( array[row][col] > target ) {
col--;
}
}
return false;
}
};
JZ11 旋转数组的最小数字
简单 通过率:34.35% 时间限制:1秒 空间限制:256M
知识点二分
描述
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
数据范围:1≤n≤10000,数组中任意元素的值: 0≤val≤10000
要求:空间复杂度:O(1) ,时间复杂度:O(logn)
示例1
输入:
[3,4,5,1,2]
返回值:
1
示例2
输入:
[3,100,200,3]
返回值:
3
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if ( 0 == rotateArray.size() ) {
return 0;
}
//如果遍历一次,开始递增,然后突然下降,然后递增,这个突然下降的元素就是最小元素
for ( int index = 0; index <= rotateArray.size()-2; index++ ) {
if ( rotateArray[index] > rotateArray[index+1] ) {
return rotateArray[index+1];
}
}
//如果遍历一次都是递增,第一个元素就是最小元素
return rotateArray[0];
}
};
JZ44 数字序列中某一位的数字
简单 通过率:34.18% 时间限制:1秒 空间限制:256M
知识点模拟
描述
数字以 0123456789101112131415… 的格式作为一个字符序列,在这个序列中第 2 位(从下标 0 开始计算)是 2 ,第 10 位是 1 ,第 13 位是 1 ,以此类题,请你输出第 n 位对应的数字。
数据范围: 0≤n≤109
示例1
输入:
0
返回值:
0
示例2
输入:
2
返回值:
2
示例3
输入:
10
返回值:
1
示例4
输入:
13
返回值:
1
class Solution {
public:
int findNthDigit(int n) {
//记录n是几位数
int digit = 1;
//记录当前区间的起始数字:1,10,100...
long long start = 1;
//记录当前区间的总共位数
//第一个区间: 9 = 9 * 1 * 1;
//第二个区间: 180 = 9 * 10 * 2;
//第三个区间: 2700 = 9 * 100 * 3
//公式:sum = 9 * start * digit
long long sum = 9;
//将n定位在某个区间
while(n > sum){
n -= sum;
start *= 10;
digit++;
//当前区间的总共位数
sum = 9 * start * digit;
}
//定位n在哪个数字
int num = start + (n - 1) / digit;
//定位n在数字中的下标
int index = (n - 1) % digit;
//根据下标直接返回数字
return to_string(num)[index] - '0';
}
};