文章目录
BM17 二分查找-I
二分使用的前提:数组中无重复元素、且有序。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型vector
* @param target int整型
* @return int整型
*/
int search(vector<int>& nums, int target) {
// write code here
int l = 0, r = nums.size() - 1;
while(l <= r){
int mid = l + (r - l) / 2;
if(nums[mid] > target) r = mid - 1;
else if(nums[mid] < target ) l = mid + 1;
else return mid;
}
return -1;
}
};
BM18 二维数组中的查找
https://www.nowcoder.com/practice/abc3fe2ce8e146608e868a70efebf62e
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
//行或列为空时数组为空,返回false
if(array.size()==0||array[0].size()==0) return false;
int i = 0, j = array[0].size()-1;
while(i<array.size()&&j>=0){
if(target<array[i][j]) j--;
else if(target>array[i][j]) i++;
else return true;
}
return false;
}
};
BM19 寻找峰值
https://www.nowcoder.com/practice/fcf87540c4f347bcb4cf720b5b350c76
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型vector
* @return int整型
*/
int findPeakElement(vector<int>& nums) {
// write code here
int l = 0, r = nums.size() - 1;
while(l<r){
int mid = l + (r - l) / 2;
// 右边是下坡路,不一定有波峰,所以r=mid
if(nums[mid] > nums[mid + 1]) r = mid;
// 右边是上坡路,一定有波峰,所以r=mid+1
else l = mid + 1;
}
//跳出循环时l>=r,l肯定是因为多跳了一步导致超过r或者与r重合
//此时结果区间不能继续更新,所以跳出时就找到了波峰,返回r
return r;
}
};
此题一个隐含做法就是找最大值,最大值一定是波峰。
BM20 数组中的逆序对
https://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5
可以使用归并排序的思想解,当右序列与左序列合并时且右序列的值<左序列才出现逆序对,逆序对的数量res += i - mid + 1(因为左序列是有序的所以在i右侧的都比j大,都会形成逆序对)。
具体细节参见本人这篇文章:https://blog.csdn.net/qq_46126258/article/details/119893952#3_105
class Solution {
public:
int mergeSort(vector<int> &a,int l,int r){
if(l>=r) return 0;
int mid = (l + r) >> 1;
int res = (mergeSort(a,l,mid) + mergeSort(a,mid+1,r))%1000000007;
int i=l,j=mid+1;
vector<int> tmp;//用于合并左右序列的临时数组
while(i<=mid && j<=r){
if(a[i]<=a[j]){
tmp.push_back(a[i++]);
}else{
tmp.push_back(a[j++]);
res += mid - i + 1;
}
}
//将剩下的放在tmp后面
while(i<=mid) tmp.push_back(a[i++]);
while(j<=r) tmp.push_back(a[j++]);
//更新a
for(int i=l,j=0;i<=r;i++,j++) a[i]=tmp[j];
return res%1000000007;
}
int InversePairs(vector<int> data) {
return mergeSort(data,0, data.size()-1);
}
};
BM21 旋转数组的最小数字
https://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba
思想参考自:https://blog.nowcoder.net/n/770b93c590f149af876b34dcf252c009
根据mid位置的值和右端的值判断旋转点的位置:
- a[mid] > a[r] :旋转点在 [ mid + 1, r ] 之间,所以左端 l 更新为 mid + 1
- a[mid] < a[r] :旋转点在 [ l, mid ] 之间,所以右端 r 更新为 mid
- a[mid] = a[r] :不能确定旋转点在左半段还是右半段,所以右端 r 更新为 r - 1 缩小判断区间
跳出循环时 l==r 此时返回二者位置之一都可以
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
int l = 0, r = rotateArray.size()-1;
while(l<r){
int mid = (l + r) >> 1;
if(rotateArray[mid]>rotateArray[r]) l = mid + 1;
else if(rotateArray[mid]<rotateArray[r]) r = mid;
else r--;
}
return rotateArray[l];
}
};
BM22 比较版本号
https://www.nowcoder.com/practice/2b317e02f14247a49ffdbdba315459e7
此题需要注意的是,比较的是相同位置的字符串对应的数字的大小,单个比较对应位置的字符是不对的。由示例5就可知只比较对应位置的字符的ASCII得出的结果是226<36但实际上数字226>36,所以一定要将字符串化为数字才能进行比较.
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 比较版本号
* @param version1 string字符串
* @param version2 string字符串
* @return int整型
*/
int compare(string version1, string version2) {
// write code here
int length1 = version1.size(),length2 = version2.size();
int i = 0, j = 0;//i指向v1,j指向v2
while(i < length1 || j < length2){
int num1 = 0, num2 = 0;
//求当前的num1
while(i < length1 && version1[i]!='.'){
num1 = num1 * 10 + (version1[i]-'0');
i++;
}
//求当前的num2
while(j < length2 && version2[j]!='.'){
num2 = num2 * 10 + (version2[j]-'0');
j++;
}
//cout<<num1<<" "<<num2<<endl;
if(num1 > num2) return 1;
else if(num1 < num2) return -1;
//指针都后移,指向下一个数字的开始
i++;
j++;
}
return 0;
}
};