441. 排列硬币
class Solution {
public:
int arrangeCoins(int n) {
if(n==1) return 1;
int l=1,r=n;
while(l<=r){
int mid=l+(r-l)/2;
if((long long)2*n>=(long long)(mid+1)*mid){
l=mid+1;
}
else{
r=mid-1;
}
}
return l-1;
}
};
暴力模拟:
class Solution {
public:
int arrangeCoins(int n) {
long now = 0; // 当前层
long count = 0; // 加上 level 层之后,总的有多少硬币
while (count + now + 1 <= n) { // level + 1 表示下一层的数目
now ++; // 得到下一层的数目
count += now; // 累加下一层的数目
}
return now;
}
};
https://ojeveryday.github.io/AlgoWiki/#/BinarySearch/README
34. 在排序数组中查找元素的第一个和最后一个位置
class Solution {
public:
int binarySearch(vector<int>& nums, int target,bool choice){
int l=0,r=nums.size()-1,res=nums.size();
while(l<=r){
int mid=l+(r-l)/2;
if(nums[mid]>target||(choice&&nums[mid]>=target)){
r=mid-1;
res=mid;
}
else{
l=mid+1;
}
}
return res;
}
vector<int> searchRange(vector<int>& nums, int target) {
int left=binarySearch(nums,target,true);
int right=binarySearch(nums,target,false)-1;
if(left<=right&&right<nums.size()&&nums[left]==target&&nums[right]==target){
return vector<int>{left,right};
}
return vector<int>{-1,-1};
}
};
33. 搜索旋转排序数组
class Solution {
public:
int search(vector<int>& nums, int target) {
if (nums.size() == 1) {
return nums[0] == target ? 0 : -1;
}
int l=0;
int r=nums.size()-1;//[l,r]
while(l<=r){//l==r区间依然有效
int mid=l+(r-l)/2;//防止溢出,等于(l+r)/2
if (target >= nums[0]) {
// 目标值在左半段时,若 mid 在右半段,则将 mid 索引的值改成 inf
if (nums[mid] < nums[0]) {
nums[mid] = INT_MAX;
}
} else {
// 目标值在右半段时,若 mid 在左半段,则将 mid 索引的值改成 -inf
if (nums[mid] >= nums[0]) {
nums[mid] = INT_MIN;
}
}
if(nums[mid]>target){
r=mid-1;//target在左区间,变为[l,mid-1]
}
else if(nums[mid]<target){
l=mid+1;//target在右区间,变为[mid+1,r]
}
else{//nums[mid]==target
return mid; //找到了返回下标mid
}
}
return -1;//没找到
}
};
74. 搜索二维矩阵
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m=matrix.size();
int n=matrix[0].size();
int l=0,r=m*n-1;
while(l<=r){
int mid=l+(r-l)/2;
int x=matrix[mid/n][mid%n];
if(x<target){
l=mid+1;
}
else if(x>target){
r=mid-1;
}
else{
return 1;
}
}
return 0;
}
};
153. 寻找旋转排序数组中的最小值
class Solution {
public:
int findMin(vector<int>& nums) {
int l = 0, r = nums.size() - 1;
if(nums[r] > nums[l]) return nums[0]; //升序数组,数组完全单调,第一个数最小
while(l < r)//不用l==r,当元素个数为1直接输出其值。
{
int mid = (l + r)/2;
if(nums[mid] < nums[0]) r = mid;
else l = mid + 1;
}
return nums[r];
}
};
有的是求值,有的求下标
162. 寻找峰值
class Solution {
public:
int findPeakElement(vector<int>& nums) {
int n=nums.size();
//特殊情况
if(n==1) return 0;
if(nums[0] > nums[1]) return 0;
if(nums[n - 1] > nums[n - 2]) return n - 1;
//正常情况
int l=0,r=n-1;
int max=0;
while(l<=r){
int mid=l+(r-l)/2;
if(mid >= 1 && mid < n - 1 &&nums[mid-1]<nums[mid]&&nums[mid]>nums[mid+1]){//避免-1和n参与计算
max=mid;
break;
}
else if(mid < n - 1 && nums[mid]<nums[mid+1]){
l=mid+1;
}
else if(mid >= 1 && nums[mid]<nums[mid-1]){
r=mid-1;
}
}
return max;
}
};