100种班服设计图/天津网站建设优化

100种班服设计图,天津网站建设优化,昆明网红街,网站开发与管理1.柠檬水找零 link:860. 柠檬水找零 - 力扣&#xff08;LeetCode&#xff09; code class Solution { public:bool lemonadeChange(vector<int>& bills) {// 贪心算法&#xff0c; 优先花出大面额bill&#xff0c; 尽可能保护小面额billint five 0, ten 0;// 不…

1.柠檬水找零

link:860. 柠檬水找零 - 力扣(LeetCode)

code

class Solution {
public:bool lemonadeChange(vector<int>& bills) {// 贪心算法, 优先花出大面额bill, 尽可能保护小面额billint five = 0, ten = 0;// 不同bill数量for(int bill : bills){if(bill == 5) five++;else if(bill == 10){ten++;if(five <= 0) return false;else five--;}else // bill == 20{if(five >= 1 && ten >= 1) five--, ten--;// 贪心else if(five >= 3) five -= 3;else return false;}}return true;}
};

交换论证法 证明:

2.将数组和减半的最少操作次数

link:2208. 将数组和减半的最少操作次数 - 力扣(LeetCode)

code

class Solution {
public:int halveArray(vector<int>& nums) {int ans = 0;double sum = 0.0;priority_queue<double> q;for(int& e : nums){sum += e;q.push(e);}double target = sum/2.0;while(target > 0){ans++;double top = q.top(); q.pop();target -= top / 2;q.push(top / 2);}return ans;}
};

交换论证法 证明:

3.最大数

link:  179. 最大数 - 力扣(LeetCode)

key:

        此问题中比较两个字符串大小:return a + b > b + a, 而不是直接return  a > b;

code

class Solution {
public:string largestNumber(vector<int>& nums) {vector<string> strs;for(int num:nums){strs.push_back(to_string(num));}sort(strs.begin(), strs.end(), [](string a, string b){return a + b > b + a;// key:不要直接使用内置的字典排序(return a > b)});string ans;for(string str:strs) ans += str;if(ans[0] == '0') return "0";return ans;}
};

4.摆动序列

link:376. 摆动序列 - 力扣(LeetCode)

tips:

        本题也可以使用动态规划解决, 时间复杂度O(n^2)

        若使用贪心算法解决此问题,时间复杂度为O(n)     

本题中如何实现贪心?

        画出折线图, 选出所有极值即可。极值个数即为最长摆动序列长度

证明贪心正确性:反证法或交换论证法

code1:

class Solution {
public:int wiggleMaxLength(vector<int>& nums) {auto it = unique(nums.begin(), nums.end());nums.erase(it, nums.end());if(nums.size() <= 2) return nums.size();int flag;// flag == 0表示摆动序列第一个为大值,1为小值flag = nums[0] > nums[1] ? 0 : 1;int ans = 1;// 第一个一定参与for(int i = 1; i < nums.size(); i++){if(flag == 0)// 找极小值{if(nums[i] < nums[i-1]) continue;else {ans++;flag = !flag;}}else// 找极大值{if(nums[i] > nums[i-1]) continue;else// nums[i-1]就是极大值{ans++;flag = !flag;}}}ans++; // 最后一个一定也为最长子序列return ans;}
};

code2:

class Solution {
public:int wiggleMaxLength(vector<int>& nums) {// 求 波峰个数 + 波谷个数即可auto it = unique(nums.begin(), nums.end());nums.erase(it, nums.end());if(nums.size() <= 2) return nums.size();int ans = 2;// nums首尾都是波峰/波谷for(int i = 1; i < nums.size() - 1; i++)// 判断除首尾的中间部分是否为波峰/波谷{if((nums[i] - nums[i-1]) * (nums[i] - nums[i+1]) > 0)// nums[i]是波峰/波谷{ans++;}}return ans;}
};

5.最长递增子序列

link:300. 最长递增子序列 - 力扣(LeetCode)

贪心思路:

        只关心长度为x的递增子序列的 最后元素的 最小值

code

class Solution {
public:int lengthOfLIS(vector<int>& nums) {// arr[i]:长度为i+1的严格递增子序列的最小末尾值vector<int> arr;arr.push_back(nums[0]);for(int i = 1; i < nums.size(); i++){if (nums[i] > arr.back()) {arr.push_back(nums[i]);continue;}// 找arr中第一个 >= nums[i] 的元素,替换为nums[i]int left = 0, right = arr.size()-1;for(; left < right; ){int mid = (left + right) / 2;if(arr[mid] >= nums[i]) right = mid;else left = mid + 1;}arr[left] = nums[i];}return arr.size();}
};

6.递增的三元子序列

link:334. 递增的三元子序列 - 力扣(LeetCode)

code

class Solution {
public:bool increasingTriplet(vector<int>& nums) {// 和300.最长递增子序列 类似, 不过此题更简单// arr[i]表示i+1长度的递增子序列中最小的结尾数vector<int> arr;arr.push_back(nums[0]);for(int i = 1; i < nums.size(); i++){if(nums[i] > arr.back()){arr.push_back(nums[i]);if(arr.size() >= 3) return true;continue;}else{// 在arr中二分查找第一个>=nums[i]的数, 替换为nums[i]int left = 0, right = arr.size() - 1;while(left < right){int mid = (left + right) >> 1;if(arr[mid] >= nums[i]) right = mid;else left = mid + 1;}arr[left] = nums[i];}}return false;}
};

7.最长连续递增序列

link:674. 最长连续递增序列 - 力扣(LeetCode)

        这是道简单题, 没什么好说的

code

class Solution {
public:int findLengthOfLCIS(vector<int>& nums) {// 贪心 + 双指针int ans = 1;for(int i = 0; i < nums.size(); i++){int j = i + 1;while(j < nums.size() && nums[j] > nums[j-1]) j++;ans = max(ans, j - i);}return ans;}
};

8.买卖股票的最佳时机

link:121. 买卖股票的最佳时机 - 力扣(LeetCode)

        由暴力枚举做优化, 用minn标记之前股票最低价位作为买入点

贪心正确性:

        一定正确, 因为其由暴力枚举优化而来, 暴力枚举一定正确, 则贪心也一定正确

code

class Solution {
public:int maxProfit(vector<int>& prices) {// 暴力枚举 -> 贪心int minn = prices[0];int ans = 0;for(int i = 1; i < prices.size(); i++){int profit = prices[i] - minn > 0 ? prices[i] - minn : 0;ans = max(ans, profit);minn = min(minn, prices[i]);}return ans;}
};

9.买卖股票的最佳时机II

link:122. 买卖股票的最佳时机 II - 力扣(LeetCode)

        与I不同的是, 此问题可以进行无数次交易

        任意相邻两天, 只要能获得正收益, 就进行交易

code1:拆分交易

        将交易都拆分为一天的交易,任意相邻两天, 只要能获得正收益, 就进行交易(一次买卖)

        

class Solution {
public:int maxProfit(vector<int>& prices) {// 拆分交易int ans = 0;int preVal = prices[0];for(int i = 1; i < prices.size(); i++){ans += max(prices[i] - preVal, 0);preVal = prices[i];}return ans;}
};

        

code2 :双指针

        低点买入, 高点卖出

class Solution {
public:int maxProfit(vector<int>& prices) {// 双指针,低点买入,高点卖出// 双指针适合用来寻找连续的,具有某种性质的区间int n = prices.size();int ans = 0;for(int i = 0; i < n; i++){int j = i; while(j + 1 < n && prices[j] < prices[j + 1]) j++;ans += prices[j] - prices[i];i = j;// 不用手动给i置为最低点}return ans;}
};

9.k次取反后最大化的数组和

link:1005. K 次取反后最大化的数组和 - 力扣(LeetCode)

tip:

        注意STL中最小堆的定义方法, 使用模板方法指明大堆/小堆:

priority_queue<int, vector<int>, greater<int>> pq(nums.begin(), nums.end());// 小堆

code

class Solution {
public:int largestSumAfterKNegations(vector<int>& nums, int k) {// 贪心:每次都取最小值进行取反priority_queue<int, vector<int>, greater<int>> pq(nums.begin(), nums.end());// 小堆while(k--){int top = pq.top();pq.pop();pq.push(-top);}int ans = 0;while(pq.size()){ans += pq.top(); pq.pop();}return ans;}
};

10.按身高排序

link:2418. 按身高排序 - 力扣(LeetCode)

tip:

        本题并不是贪心算法题, 只是一道普通排序题,为下一道题做铺垫

code1:绑定排序

将heights与names绑定在一起, 按照heights排序

class Solution {
public:vector<string> sortPeople(vector<string>& names, vector<int>& heights) {vector<tuple<int, string>> hn;for(int i = 0; i < names.size(); i++){hn.push_back({heights[i], names[i]});}sort(hn.begin(), hn.end(), [](tuple<int, string>& hn1, tuple<int, string>& hn2){return get<0>(hn1) > get<0>(hn2);}// 手动实现greater);vector<string> ans;for(tuple<int, string> e:hn){ans.push_back(get<1>(e));}return ans;}
};

code2(非常实用):对下标排序

新建数组indexs从0到heights.size()-1,对应heights下标,再根据heights对indexs排序

class Solution {
public:vector<string> sortPeople(vector<string>& names, vector<int>& heights) {// 下标排序vector<int> indexs;for(int i = 0; i < names.size(); i++){indexs.push_back(i);}sort(indexs.begin(), indexs.end(), [&heights](int i, int j){return heights[i] > heights[j];});vector<string> ans;for(int i:indexs){ans.push_back(names[i]);}return ans;}
};

11.优势洗牌

link:870. 优势洗牌 - 力扣(LeetCode)

key:

        用最小的 大于nums2[i]的nums1元素来匹配nums[i]
        剩下的nums1元素用来匹配剩下的nums2元素,每次用最小的nums1匹配最大的nums2

可以使用交换论证法来证明贪心策略正确性

code

class Solution {
public:vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) {// 田忌赛马// 用最小的 大于nums2[i]的nums1元素来匹配nums[i]// 剩下的nums1元素用来匹配剩下的nums2元素,每次用最小的nums1匹配最大的nums2int n = nums1.size();vector<int> indexs2;// nums2的下标映射for(int i = 0; i < nums2.size(); i++){indexs2.push_back(i);}sort(nums1.begin(), nums1.end());sort(indexs2.begin(), indexs2.end(), [&nums2](int i, int j){return nums2[i] < nums2[j];});// 用index2代替nums2排序 // 双指针vector<int> tmp(n, 0);for(int left = 0, right = n - 1, p1 = 0; left <= right; p1++){if(nums1[p1] > nums2[indexs2[left]]){tmp[left++] = nums1[p1];}else {tmp[right--] = nums1[p1];}}// 恢复排序vector<int> ans(n, 0);for(int i = 0; i < n; i++){ans[indexs2[i]] = tmp[i];}return ans;}
};

12.最长回文串

link:409. 最长回文串 - 力扣(LeetCode)

这是道简答题,不多说明

code

class Solution {
public:int longestPalindrome(string s) {int hash[256];memset(hash, 0, sizeof hash);for(char ch:s){hash[ch]++;}int arr[2] = {0};for(int e : hash){arr[0] += e/2 * 2;arr[1] += e%2;}int ans = arr[0] + (arr[1] ? 1 : 0);return ans;}
};

13.增减字符串匹配

link:942. 增减字符串匹配 - 力扣(LeetCode)

贪心策略:每次I选最小, 每次D选最大

证明贪心策略正确性:归纳法

        当s[i] = ‘I'时, ans[i]选择当前最小值,则之后所有ans都比ans[i]大,这种情况一定满足题意

        同理可证s[i] = ‘D',ans[i]选当前最大值, 则之后所有ans都比ans[i]小, 这种情况一定满足题意

code

class Solution {
public:vector<int> diStringMatch(string s) {// 贪心, 每次I选最小, 每次D选最大int n = s.size();int minn = 0, maxx = n;vector<int> ans(n + 1, 0);for(int i = 0; i < n; i++){ans[i] = s[i] == 'I' ? minn++ : maxx--;}ans[n] = minn;//此时minn = maxxreturn ans;}
};

14.分发饼干

link:455. 分发饼干 - 力扣(LeetCode)

其实就是田忌赛马, 相当于询问田忌赛马最多胜利的场数

贪心策略:优先先满足最小胃口孩子的需求(用最小的满足其胃口的饼干)

贪心策略正确性证明见本文第11题“优势洗牌”(交换论证法)

code

class Solution {
public:int findContentChildren(vector<int>& g, vector<int>& s) {// 贪心策略:优先先满足最小胃口孩子的需求(用最小的满足其胃口的饼干),类似田忌赛马int ans = 0;sort(g.begin(), g.end());sort(s.begin(), s.end());     for(int ps = 0, pg = 0; ps < s.size() && pg < g.size(); ps++){printf("s[ps] = %d, g[pg] = %d\n", s[ps], g[pg]);if(s[ps] >= g[pg]){ans++;pg++;}}return ans;}
};

15.最优除法

link:553. 最优除法 - 力扣(LeetCode)

贪心策略:让nums[0]为分子,其他均为分母即可
 key:nums[0]比为分子,nums[1]必为分母

由于nums[i] >2,易得贪心策略一定为最优解

code

class Solution {
public:string optimalDivision(vector<int>& nums) {// 贪心策略:让nums[0]为分子,其他均为分母即可// key:nums[0]比为分子,nums[1]必为分母if(nums.size() == 1) return to_string(nums[0]);if(nums.size() == 2) return to_string(nums[0]) + '/' + to_string(nums[1]);string ans;ans += to_string(nums[0]) + "/(" + to_string(nums[1]);for(int i = 2; i < nums.size(); i++){ans += '/' + to_string(nums[i]);}ans += ')';return ans;}
};

16.跳跃游戏II

link:45. 跳跃游戏 II - 力扣(LeetCode)

贪心策略:选择能跳的最远的点作为下一个点(选择i + nums[i]最大的i点)

code

class Solution {
public:int jump(vector<int>& nums) {// 贪心策略:选择能跳的最远的点作为下一个点(选择i + nums[i]最大的i点)int ans = 0;int cur = 0;int n = nums.size();while(cur < nums.size()-1){// 题目保证可以到达终点则nums[cur] != 0if(nums[cur] == 0){printf("error, nums[cur] == 0\n");return -1;}int nextStep = cur + 1, farest = cur + nums[cur];if(farest >= n - 1) return ans + 1;for(int i = cur + 1; i <= cur + nums[cur]; i++){if(i + nums.at(i) > farest){nextStep = i;farest = i + nums.at(i);}}cur = nextStep;ans++;}return ans;}
};

17.跳跃游戏

link:55. 跳跃游戏 - 力扣(LeetCode)

与跳跃游戏II类似,不多解释

code

class Solution {
public:bool canJump(vector<int>& nums) {// 贪心策略:每次选择能跳的最远的点为下一个点(选令i+nums[i]最大的i最为下一个点// 下一个点的nums[i]为0则return falseint left = 0, right = 0;// 下一个点的选取区间int nextStep = 0, farest = 0 + nums[0];int cur = 0;while(cur < nums.size() - 1){if(nums[cur] == 0) return false;left = cur + 1;right = cur + nums[cur];if(right >= nums.size()-1) return true;nextStep = cur + 1;for(int i = left; i <= right; i++){if(i + nums[i] > farest){farest = i + nums[i];nextStep = i;}}cur = nextStep;}return true;}
};

18.加油站

link:134. 加油站 - 力扣(LeetCode)

本题贪心方案不是很明显,值得仔细分析

贪心策略:

        每次只从diff[i] >= 0的位置开始,若遇到不能递达的站点j,则更新i为j([i, j]内所有站点都不满足条件)

        diff[i] = gas[i] - cost[i]

code

class Solution {
public:int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {// 暴力枚举 -> 贪心(改变i更新逻辑)vector<int> diff;for(int i = 0; i < gas.size(); i++){diff.push_back(gas[i]-cost[i]);}for(int i = 0; i < diff.size(); i++){if(diff[i] < 0) continue;int sum = 0;for(int cur = i; cur < i + diff.size(); cur++){sum += diff[cur % diff.size()];if(sum < 0){i = cur;// key:改变i的更新逻辑break;}}if(sum >= 0) return i;}return -1;}
};

19.单调递增的数字

link:738. 单调递增的数字 - 力扣(LeetCode)

        贪心策略:若n合法,直接返回n; 若n不合法,返回最大位-1,后接多个9(此策略有暴力枚举优化而来)

        贪心原理正确性:如果n本身不满足条件,为了保持递增性, 最后一个递增元素一定要减1, 在此情况下将其后所有元素置为9,既满足递增条件,又保证是最大值。即为最优解。

        也可以使用反证法证明贪心策略正确性,自行证明比答案大的数不满足递增条件即可

code

class Solution {
public:int monotoneIncreasingDigits(int n) {// 贪心策略:若n合法,直接返回n; 若n不合法,返回最大位-1,后接多个9(此策略有暴力枚举优化而来)// 如果n本身不满足条件,为了保持递增性, 最后一个递增元素一定要减1, 在此情况下将其后所有元素置为9,即为最优解if(n <= 9) return n;string sn = to_string(n);bool valied = true;int end = 0;// 最后一个递增元素的下标for(int i = 0; i < sn.size() - 1; i++){if(sn[i] > sn[i + 1]) {valied = false;end = i;break;}}if(valied) return n;string ans = sn.substr(0, end) + func(sn.substr(end, string::npos));return monotoneIncreasingDigits(stoi(ans));// 防止s[i-1] > s[i]}string func(string str){string ret = to_string(str[0] - '0' - 1);for(int i = 1; i < str.size(); i++){ret += "9";}return ret;}
};

20.坏了的计算器

link:991. 坏了的计算器 - 力扣(LeetCode)

        key:正难则反,交换startValue与target ,/ - 改为 * +

        贪心策略:能除就除

code

class Solution {
public:int brokenCalc(int startValue, int target) {// 正难则反,转化为target->startValue, 只能/2 或 +1swap(startValue, target);int ans = 0;while(startValue != target){if(startValue % 2 == 1) {startValue += 1;}else{if(startValue > target) startValue /= 2;else startValue += 1;}ans++;}return ans;}
};

21.合并区间

link:56. 合并区间 - 力扣(LeetCode)

贪心策略:每次选择最小start最小的区间

code

class Solution {
public:vector<vector<int>> merge(vector<vector<int>>& intervals) {// 贪心策略:每次选择最小start最小的区间sort(intervals.begin(), intervals.end(), [](vector<int>& vc1, vector<int>& vc2){return vc1[0] < vc2[0];});vector<vector<int>> ans;int left = intervals[0][0], right = intervals[0][1];for(int i = 1; i < intervals.size(); i++){int start = intervals[i][0], end = intervals[i][1];if(start <= right){right = max(right, end);}else{ans.push_back({left, right});left = start, right = end;}}ans.push_back({left, right});return ans;}
};

22.无重叠区间

link:435. 无重叠区间 - 力扣(LeetCode)

        正难则反:求使得区间互不重叠的区间的最大数量

       贪心策略:优先选择终点最小的区间

tips:

        一般来讲,区间问题中,既可以左端点排序,也可右端点排序。本题也是如此,只不过本题中使用右端点排序更加直观,容易理解

        若本题使用左端点排序,则在每次重叠时选择end最小的区间即可

        区间问题常用贪心算法

code(右端点排序)

class Solution {
public:int eraseOverlapIntervals(vector<vector<int>>& intervals) {// 正难则反:求使得区间互不重叠的区间的最大数量// 贪心策略:优先选择终点最小的区间sort(intervals.begin(), intervals.end(), [](vector<int>& vc1, vector<int>& vc2){return vc1[1] < vc2[1];});int left = intervals[0][0], right = intervals[0][1];int maxx = 1;for(int i = 1; i < intervals.size(); i++){if(intervals[i][0] >= right) {maxx++;right = intervals[i][1];}else continue;}return intervals.size() - maxx;}
};

code2-左端点排序

每次重叠时选择end最小的区间

本解法直接求需要删去的区间的个数

class Solution {
public:int eraseOverlapIntervals(vector<vector<int>>& intervals) {// 左端点排序sort(intervals.begin(), intervals.end(), [](vector<int>& vc1, vector<int>& vc2){return vc1[0] < vc2[0];});// 删除区间int right = intervals[0][1];int ans = 0;for(int i = 1; i < intervals.size(); i++){if(intervals[i][0] < right)// 重叠{ans++;right = min(right, intervals[i][1]);}else right = intervals[i][1];}return ans;}
};

23.用最少数量的箭引爆气球

link:452. 用最少数量的箭引爆气球 - 力扣(LeetCode)

与上题类似,与重叠区间有关

         贪心策略:左端点排序,顺序遍历

        与前组有重叠则更新交集,不重叠就射箭全部戳破,并更新交集

code

class Solution {
public:int findMinArrowShots(vector<vector<int>>& points) {// 贪心策略:左端点排序,顺序遍历// 与前组有重叠则更新交集,不重叠就射箭全部戳破,并更新交集sort(points.begin(), points.end(), [](vector<int>& vc1, vector<int>& vc2){return vc1[0] < vc2[0];});int right = points[0][1];int ans = 0;for(int i = 1; i < points.size(); i++){if(points[i][0] > right)// 不重叠{ans++;right = points[i][1];}else right = min(right, points[i][1]);}return ans + 1;}
};

24.整数替换

link:397. 整数替换 - 力扣(LeetCode)

code1--dfs模拟

class Solution {
public:unordered_map<int, int> hash;int integerReplacement(int n) {// 直接模拟(dfs 记忆化搜索)return dfs(n);}int dfs(long long n){if(hash.count(n)) return hash[n];int ret;if(n == 1){hash[1] = 1;ret = 0;}else if(n % 2 == 0){ret =  (1 + dfs(n / 2));}else{ret =  1 + min(dfs(n + 1), dfs(n - 1));}hash[n] = ret;return ret;}
};

code2--贪心

以二进制视角看待n

class Solution {
public:int integerReplacement(int n) {int ans = 0;long long cur = n;while(cur != 1){if(cur % 2 == 0) cur /= 2;else{if(cur == 3) cur-=1;else if(cur % 4 == 1) cur -= 1;else cur += 1;}ans++;}return ans;}
};

25.俄罗斯套娃信封问题

link:354. 俄罗斯套娃信封问题 - 力扣(LeetCode)

左端点排序+贪心+二分

排序后求右端点的最长递增子序列即可

tips:

        排序时,若左端点相同, 则按照右端点降序排序,这样可以保证最长递增子序列不出现同左端点的元素

        本题也可以用动态规划代替贪心+二分部分,虽然这样会超市(时间复杂度O(N), 但动态规划是一种应用更加广泛,也更简单易懂的算法。但是为了降低时间复杂度,本题解使用贪心算法解决本问题

code

class Solution {
public:int maxEnvelopes(vector<vector<int>>& evs) {// 转化为最长递增子序列即可(左端点排序 + 重写排序)sort(evs.begin(), evs.end(), [](vector<int>& vc1, vector<int>& vc2){if(vc1[0] != vc2[0]) return vc1[0] < vc2[0];else return vc1[1] > vc2[1];}); // 重写排序,令左端点相同的元素们按照右端点降序,保证最长递增子序列中,同左端点的元素只出现一次// 寻找右端点最长递增子序列(贪心方法)vector<int> vc(1, -1);// vc[i]表示长度为i的最长递增子序列的最小结尾值for(vector<int> ev :evs){int val = ev[1];if(val > vc.back()){vc.push_back(val);continue;}// vc 是升序的, 二分查找第一个大于等于val的元素下标int left = 1, right = vc.size() - 1;for(; left < right; ){int mid = (left + right) >> 1;if(vc[mid] >= val) right = mid;else left = mid + 1;}vc[left] = val;}// chechfor(int e:vc){printf("%d ", e);}return vc.size() - 1;}
};

26.可被三整除的最大和

link:1262. 可被三整除的最大和 - 力扣(LeetCode)

tip:

        因为本题mod3,3比较小,所以可以使用贪心+分情况讨论。

        但是但是如果将3换为更大的数,贪心时的分类讨论会特别麻烦,此时我们就应该使用多状态动态规划

        本题code可以稍微优化:可以先将两个mod3==1与两个mod3==2的最小的数求出,避免不同情况重复求共同值

code

class Solution {
public:int maxSumDivThree(vector<int>& nums) {// 正难则反:先求nums的sum,再分类讨论如何舍去较小元素使能sum被三整除// 因为本题是mod3,3比较小,所以可以使用分类讨论+贪心,但是如果将3换为更大的数,贪心时的分类讨论会特别麻烦,此时我们就应该使用多状态动态规划sort(nums.begin(), nums.end());const int INF = 0x3f3f3f3f;int ans;int sum = 0;for(int num:nums) sum += num;if(sum % 3 == 0) return sum;else if(sum % 3 == 1) {// 情况一:去除最小的mod3 == 1的元素int a = INF;for(int num:nums){if(num % 3 == 1){a = num;break;}}// 情况二:去除最小的两个mod3 == 2的元素vector<int> b;for(int num:nums){if(num % 3 == 2){b.push_back(num);if(b.size() >= 2) break;}}int sub = a; if(b.size() >= 2) sub = min(sub, b[0] + b[1]);ans = sum - sub;}   else // sum % 3 == 2{// 情况一:减去两个mod3 == 1的最小元素vector<int> a;for(int num:nums){if(num % 3 == 1){a.push_back(num);if(a.size() >= 2) break;}}// 情况二:减去最小的mod3 == 2的元素int b = INF;for(int num:nums){if(num % 3 == 2) {b = num;break;}}int sub = b; if(a.size() >= 2) sub = min(sub, a[0] + a[1]);ans = sum - sub;}return ans;}
};

27.距离相等的条形码

link:1054. 距离相等的条形码 - 力扣(LeetCode)

        贪心+模拟

       

code1

        key:只要保证所有元素都不和其前一个元素重复即可

        每次选择剩余的相同数量最大的且不与前一个元素重复的num

class Solution {
public:static bool cmp(pair<int, int>& pr1, pair<int, int>& pr2){return pr1.first < pr2.first;}vector<int> rearrangeBarcodes(vector<int>& bs) {// 贪心+模拟// key:只要保证所有元素都不和其前一个元素重复即可unordered_map<int, int> num_cnt;vector<int> ans;for(int b:bs){num_cnt[b]++;}priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> pq(cmp);for(auto [num, cnt]:num_cnt){pq.push({cnt, num});}// 开始模拟pair<int, int> prePair = pq.top(); pq.pop();ans.push_back(prePair.second);prePair.first--;while(pq.size()){pair<int, int> pr = pq.top(); pq.pop();ans.push_back(pr.second);pr.first--;if(prePair.first > 0)pq.push(prePair);prePair = pr;}return ans;}
};

code2

        先摆放在偶数下标位置, 后摆放再奇数下标位置。

        只要保证cnt最多的num先摆放即可,剩下的数的摆放顺序无所谓(但是相同的数要连续顺序摆放)

class Solution {
public:vector<int> rearrangeBarcodes(vector<int>& bs) {// 贪心+模拟 (code2分割法unordered_map<int, int> num_cnt;int maxCnt = 0;int mostNum = 0;for(int b:bs) {if(++num_cnt[b] > maxCnt){maxCnt = num_cnt[b];mostNum = b;}}printf("maxCnt = %d, mostNum = %d\n", maxCnt, mostNum);// 模拟vector<int> ans(bs.size(), 0);for(int i = 0; i < maxCnt; i++){ans[i*2] = mostNum;}num_cnt.erase(mostNum);int idx = maxCnt * 2;for(auto& [num, cnt]:num_cnt){for(int i = 0; i < cnt; i++){if(idx >= ans.size()) idx = 1;ans[idx] = num;idx += 2;}}return ans;}
};

28.重构字符串

link:767. 重构字符串 - 力扣(LeetCode)

        与上题“距离相等的条形码"相同,只不过参数从vector<int>改为了string

        判断特殊情况, 之后直接复用上题代码即可

code

class Solution {
public:string reorganizeString(string s) {//  同1054.距离相等的条形码int sz = s.size();unordered_map<char, int> ch_cnt;int maxCnt = 0;char mostChar = 0;for(char ch:s) {if(++ch_cnt[ch] > maxCnt){maxCnt = ch_cnt[ch];mostChar = ch;}}if(maxCnt > (sz + 1) / 2) return "";vector<int> vc(s.begin(), s.end());vector<int> ret = rearrangeBarcodes(vc);string ans;for(char ch:ret){ans += ch;}return ans;}static bool cmp(pair<int, int>& pr1, pair<int, int>& pr2){return pr1.first < pr2.first;}vector<int> rearrangeBarcodes(vector<int>& bs) {// 贪心+模拟// key:只要保证所有元素都不和其前一个元素重复即可unordered_map<int, int> num_cnt;vector<int> ans;for(int b:bs){num_cnt[b]++;}priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> pq(cmp);for(auto [num, cnt]:num_cnt){pq.push({cnt, num});}// 开始模拟pair<int, int> prePair = pq.top(); pq.pop();ans.push_back(prePair.second);prePair.first--;while(pq.size()){pair<int, int> pr = pq.top(); pq.pop();ans.push_back(pr.second);pr.first--;if(prePair.first > 0)pq.push(prePair);prePair = pr;}return ans;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/72991.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于YOLO11深度学习的电瓶车进电梯检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

github生成badges的方法

在Github页面上生成类似下面这样的badge的方法 你可以通过以下步骤在GitHub个人主页的README中创建类似的技术栈徽章&#xff1a; 一、使用 Shields.io 生成徽章 Shields.io 是一个开源徽章生成工具&#xff0c;支持自定义文本、颜色、图标等参数。 1. 基础模板 https://…

vue3 二次封装uni-ui中的组件,并且组件中有 v-model 的解决方法

在使用uniappvue3开发中&#xff0c; 使用了uni-ui的组件&#xff0c;但是我们也需要自定义组件&#xff0c;比如我要自定一个picker 的组件&#xff0c; 是在 uni-data-picker 组件的基础上进行封装的 父组件中的代码 <classesselect :selectclass"selectclass"…

爬虫案例七Python协程爬取视频

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Python协程爬取视频 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 爬虫案例七协程爬取视频 提示&#xff1a;以下是本篇文章正文…

Python 爬虫实战案例 - 获取拉勾网招聘职位信息

引言 拉勾网&#xff0c;作为互联网招聘领域的佼佼者&#xff0c;汇聚了海量且多样的职位招聘信息。这些信息涵盖了从新兴科技领域到传统行业转型所需的各类岗位&#xff0c;无论是初出茅庐的应届生&#xff0c;还是经验丰富的职场老手&#xff0c;都能在其中探寻到机遇。 对…

LM Studio 替换源的方式解决huggingface.co无法访问的问题

安装软件完成之后&#xff0c;不要打开&#xff0c;打开了就直接关闭 在安装目录下&#xff0c;比如我安装在E:\Program Files\LM Studio 下面三个文件中的huggingface.co全部替换为hf-mirror.com然后再打开即可。 E:\Program Files\LM Studio\resources\app\.webpack\rende…

【模拟CMOS集成电路设计】带隙基准(Bandgap)设计与仿真(基于运放的电流模BGR)

【模拟CMOS集成电路设计】带隙基准&#xff08;Bandgap&#xff09;设计与仿真 前言工程文件&部分参数计算过程&#xff0c;私聊~ 一、 设计指标指标分析&#xff1a; 二、 电路分析三、 仿真3.1仿真电路图3.2仿真结果(1)运放增益(2)基准温度系数仿真(3)瞬态启动仿真(4)静态…

微服务拆分-远程调用

我们在查询购物车列表的时候&#xff0c;它有一个需求&#xff0c;就是不仅仅要查出购物车当中的这些商品信息&#xff0c;同时还要去查到购物车当中这些商品的最新的价格和状态信息&#xff0c;跟购物车当中的快照进行一个对比&#xff0c;从而去提醒用户。 现在我们已经做了服…

P2P中NAT穿越方案(UDP/TCP)(转)

转自&#xff1a;P2P中NAT穿越方案&#xff08;UDP/TCP&#xff09;_udp反向链接-CSDN博客 同&#xff1a;P2P中NAT穿越方案&#xff08;UDP/TCP&#xff09; - 知乎 (zhihu.com) 本文介绍了传统基于udp的打洞方式&#xff0c;更进一步阐述了tcp打洞的原理&#xff0c;是对于…

算法 之 树形dp 树的中心、重心

文章目录 重心实践题目小红的陡峭值 在树的算法中&#xff0c;求解树的中心和重心是一类十分重要的算法 求解树的重心 树的重心的定义&#xff1a;重心是树中的一个节点&#xff0c;如果将这个点删除后&#xff0c;剩余各个连通块中点数的最大值最小&#xff0c;那么这个节点…

游戏引擎学习第146天

音高变化使得对齐读取变得不可能&#xff0c;我们可以支持循环声音了。 我们今天的目标是完成之前一段时间所做的音频代码。这个项目并不依赖任何引擎或库&#xff0c;而是一个教育项目&#xff0c;目的是展示从头到尾运行一个游戏所需要的全部代码。无论你对什么方面感兴趣&a…

深入理解MySQL主从原理

导读 高鹏&#xff08;网名八怪&#xff09;&#xff0c;《深入理解MySQL主从原理》系列文的作者。 本系列通过GTID、Event、主库、从库、案例分析&#xff0c;五大块来详细讲解主从原理。 这篇文章重在学习笔记整理&#xff01; 在学习《深入理解MySQL主从原理》一书时&…

Phi-4-multimodal:图、文、音频统一的多模态大模型架构、训练方法、数据细节

Phi-4-Multimodal 是一种参数高效的多模态模型&#xff0c;通过 LoRA 适配器和模式特定路由器实现文本、视觉和语音/音频的无缝集成。训练过程包括多阶段优化&#xff0c;确保在不同模式和任务上的性能&#xff0c;数据来源多样&#xff0c;覆盖高质量网络和合成数据。它的设计…

Unity--Cubism Live2D模型使用

了解LIVE2D在unity的使用--前提记录 了解各个组件的作用 Live2D Manuals & Tutorials 这些文件都是重要的控制动画参数的 Cubism Editor是编辑Live2D的工具&#xff0c;而导出的数据的类型&#xff0c;需要满足以上的条件 SDK中包含的Cubism的Importer会自动生成一个Pref…

Linux | Vim 鼠标不能右键粘贴、跨系统复制粘贴

注&#xff1a;本文为 “ Vim 中鼠标右键粘贴、跨系统复制粘贴问题解决方案” 相关文章合辑。 未整理去重。 Linux 入门&#xff1a;vim 鼠标不能右键粘贴、跨系统复制粘贴 foryouslgme 发布时间 2016 - 09 - 28 10:24:16 Vim基础 命令模式(command-mode)插入模式(insert-m…

Flink-DataStreamAPI-执行模式

一、概览 DataStream API支持不同的运行时执行模式&#xff0c;我们可以根据用例的要求和作业的特征进行选择。 STREAMING执行模式&#xff1a;被称为“经典”执行模式为&#xff0c;主要用于需要持续增量处理并且预计无限期保持在线的无界作业BATCH执行模式&#xff1a;类似…

解决VScode 连接不上问题

问题 &#xff1a;VScode 连接不上 解决方案&#xff1a; 1、手动杀死VS Code服务器进程&#xff0c;然后重新尝试登录 打开xshell &#xff0c;远程连接服务器 &#xff0c;查看vscode的进程 &#xff0c;然后全部杀掉 [cxqiZwz9fjj2ssnshikw14avaZ ~]$ ps ajx | grep vsc…

使用阿里云操作系统控制台排查内存溢出

引言 操作系统控制台是阿里云最新推出的一款智能运维工具&#xff0c;专为提升运维效率、优化服务器管理而设计。它集成了多种运维管理功能&#xff0c;包括操作系统助手、插件管理器以及其他实用工具&#xff0c;为用户提供一站式的运维解决方案。无论是个人开发者还是企业运…

混合存储HDD+SSD机型磁盘阵列,配上SSD缓存功能,性能提升300%

企业日常运行各种文件无处不在&#xff0c;文档、报告、视频、应用数据......面对成千上万的文件&#xff0c;团队之间需要做到无障碍协作&#xff0c;员工能够即时快速访问、共享处理文件。随着业务增长&#xff0c;数字化办公不仅需要大容量&#xff0c;快速高效的文件访问越…

二级Python通关秘籍:字符串操作符/函数/方法全解析与实战演练

第一章 字符串基础概念与运算符速通 1.1 字符串的不可变性特性 在Python中&#xff0c;字符串被设计为immutable类型&#xff0c;任何修改操作都会生成新对象。这一特性直接影响字符串拼接的性能表现&#xff0c;建议使用join()方法代替多次操作。 1.2 基础操作符全掌握 pyt…