二分|组合|旋转数组
lc1976
dijk min_path
pq. min_w
lcr187
同lc1823.约瑟夫环
class Solution {
public:
int iceBreakingGame(int num, int target)
{
int x=0;
for(int i=2;i<=num;i++)
{
x=(x+target)%i;
}
return x;
}
};
lc2972
计算数组中可移除的子数组数量
先找最长递增前缀,再结合递增后缀统计符合条件的情况
class Solution {
typedef long long ll;
public:
long long incremovableSubarrayCount(vector<int>& a) {
int n = a.size();
int i = 0;
while (i < n - 1 && a[i] < a[i + 1]) {
i++;
}
if (i == n - 1) {
// 每个非空子数组都可以移除
return (ll)n * (n + 1) / 2;
}
ll ans = i + 2;
// 不保留后缀的情况,一共 i+2 个
// 枚举保留的后缀为 a[j:]
for (int j = n - 1; j == n - 1 || a[j] < a[j + 1]; j--) {
while (i >= 0 && a[i] >= a[j]) {
i--;
}
// 可以保留前缀 a[:i+1], a[:i], ..., a[:0] 一共 i+2 个
ans += i + 2;
}
return ans;
}
};
lcp02
倒着连分数,把“里面的分数”先算好,再一层层包进“外面的数”里。
int up=1;
int down=0;
for(int i=cont.size()-1;i>=0;i--){
swap(up,down); //up变分母后
up+=cont[i]*down; //更新计算
}
return{up,down};
class Solution {
public:
vector<int> fraction(vector<int>& cont) {
int up=1;
int down=0;
for(int i=cont.size()-1;i>=0;i--){
swap(up,down); //up变分母后
up+=cont[i]*down; //更新计算
}
return{up,down};
}
};
左闭右开
lc153 无重复元素
class Solution {
public:
int findMin(vector<int>& nums)
{
int n=nums.size();
int l=0,r=n-1;
while(l<r)
{
int mid=l+(r-l)/2;
if(nums[mid]>nums[r])
l=mid+1;
else
r=mid;
}
return nums[l];
}
};
lc154
二分法,左闭右开
当中间值和最右值相等时
右边界r-- 左移一步,缩小范围,排除重复元素干扰,最终找到最小值。
class Solution {
public:
int findMin(vector<int>& nums)
{
int n = nums.size();
int l = 0, r = n - 1;
while (l < r) {
int mid = l + (r - l) / 2;
if (nums[mid] > nums[r])
l = mid + 1;
else if (nums[mid] < nums[r])
// 右边界更新为mid(保留mid可能为最小值的情况)
r = mid;
else
r--;
}
return nums[l];
}
};