山脉二分找中值|子集型回溯

++回溯枚举情况 出口处check++

lc1601

不选 选

++DFS枚举所有请求的选与不选,统计++满足所有节点进出人数平衡的请求组合,返回最大请求数量

class Solution {

public:

int maximumRequests(int n, vector<vector<int>>& requests) {

int ans = 0;

int l = requests.size();

vector<int> path(n,0);

//i表示当前遍历的元素,cnt是当前满足的请求

function<void(int,int)> dfs = \&(int i,int cnt)

{

if(i==l)

{

for(int k = 0;k < n;++k)

++if(pathk != 0) return; //check
ans = max(ans,cnt);
++

return;

}

//不选

dfs(i+1,cnt);

//选

pathrequests\[i0]--;//出去

pathrequests\[i1]++;//进去

dfs(i+1,cnt+1);

//恢复现场

pathrequests\[i0]++;//出去

pathrequests\[i1]--;//进去

};

dfs(0,0);

return ans;

}

};

lc2044

之前是用for迭代写的

刷题单发现还可以回溯写(`・ω・´)

先计算数组所有元素的总按位或值

再通过DFS枚举子集,统计按位或等于该最大值的子集数量

trick:

if (subset_or == total_or)

ans += 1 << (n - i);

当子集按位或等于最大值时,剩++余 n-i 个元素选或不选都不影响结果++,直接用 2^(n-i) 快速统计这类子集的数量。

class Solution {

/*

输入:nums = 3,2,1,5

输出:6

解释:子集按位或可能的最大值是 7 。有 6 个子集按位或可以得到 7 :

  • 3,5

  • 3,1,5

  • 3,2,5

  • 3,2,1,5

  • 2,5

  • 2,1,5

*/

public:

int countMaxOrSubsets(vector<int>& nums) {

int ++total_or = reduce(nums.begin(), nums.end(), 0, bit_or());++

int n = nums.size();

int ans = 0;

auto dfs = \&(this auto&& dfs, int i, int subset_or) {

++if (subset_or == total_or) {
ans += 1 << (n - i);
++

return; //cut

}

if (i == n)

return;

dfs(i + 1, subset_or); // 不选 numsi

dfs(i + 1, ++subset_or | numsi); // 选++

};

dfs(0, 0);

return ans;

}

};

lc1255

预处理: 统计字母库存后

DFS枚举单词选或不选的所有组合

验证字母是否充足并计算得分,最终返回最大得分

class Solution {

public:

int maxScoreWords(vector<string> &words, vector<char> &letters, vector<int> &score) {

int ans = 0, left26{};

for (char c : letters)

++leftc - 'a';

function<void(int, int)> dfs = \&(int i, int total)

{

if (i < 0) { // 到头了

++ans = max(ans, total);++

return;

}

// 不选 wordsi

dfs(i - 1, total);

// 选 wordsi

bool ok = true;

for (char c : wordsi) {

++if (leftc - 'a'-- == 0)++

++ok = false; // 剩余字母不足++

++total += scorec - 'a'; // 累加得分++

}

if (ok)

++dfs(i - 1, total);++

// 恢复现场

++for (char c : wordsi)++

++++leftc - 'a';++

};

dfs(words.size() - 1, 0);

return ans;

}

};

lc1095

山脉数组 两次二分

先二分查找山脉数组的峰值位置

再在峰值左侧升序区间和右侧降序区间分别二分查找目标值

优先返回左侧找到的索引

/**

* // This is the MountainArray's API interface.

* // You should not implement it, or speculate about its implementation

* class MountainArray {

* public:

* int get(int index);

* int length();

* };

*/

class Solution

{

public:

int binary_search(MountainArray & mountainArr, int target, int L, int R, int sign)

{

target = sign * target;

while (L <= R)

{

int mid = (L + R) >> 1;

int cur = sign * mountainArr.get(mid);

if (cur == target)

return mid;

else if (cur < target)

L = mid + 1;

else

R = mid - 1;

}

return -1;

}

int findInMountainArray(int target, MountainArray &mountainArr)

{

int L = 0, R = mountainArr.length() - 1;

while (L <= R)

{

int mid = (L + R) >> 1;

if (mountainArr.get(mid) < mountainArr.get(mid + 1))

L = mid + 1;

else

R = mid-1;

}

int peak_idx = L;

int idx = binary_search(mountainArr, target, 0, peak_idx, 1 );

if (idx != -1)

return idx;

return binary_search(mountainArr, target, peak_idx + 1, mountainArr.length() - 1, -1 );

}

};

相关推荐
INGNIGHT10 小时前
270 · 电话号码的字母组合II(Trie)
linux·算法
2401_8390805410 小时前
C++常见八股
数据结构·c++·算法
青山是哪个青山11 小时前
LeetCode 188:买卖股票的最佳时机 IV
算法
mikuyyds11 小时前
geo-toolbox 插件算法解析:RUSLE 与 MUSLE 的工程化落地
算法·rust·gis
a1879272183111 小时前
【算法】树(二):队列与祖先——BFS 骨架三配件、短路透传与合流
算法·leetcode·二叉树··bfs·算法讲解·树遍历
syagain_zsx12 小时前
算法基础篇 · 03 枚举(C++ 题解)
c++·算法·二进制·枚举
weixin_3077791312 小时前
C++代码实现MATLAB中的ode23tb函数功能
开发语言·c++·算法·matlab
我是章汕呐13 小时前
地级市能源消耗量及消耗强度数据【2006-2023年】平衡面板
人工智能·经验分享·算法·回归
charliejohn13 小时前
计算机考研 408 数据结构 堆的插入与删除 堆排序
算法
老鱼说AI14 小时前
从点积到希尔伯特空间:向量内积的几何本质与大模型相似度度量
人工智能·深度学习·线性代数·算法·机器学习·数学建模