p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica }
【44】Wildcard Matching
【45】Jump Game II (2018年11月28日,算法群衍生题)
题目背景和 55 一样的,问我能到达最后一个index的话,最少走几步。
题解:
【55】Jump Game (2018年11月27日,算法群)
给了一个数组nums,nums[i] = k 代表站在第 i 个位置的情况下, 我最多能往前走 k 个单位。问我能不能到达最后一个 index。
题解:虽然是贪心分类,我还是用dp解了。dp[i] 代表我能不能到达第 i 个位置。
1 class Solution { 2 public: 3 bool canJump(vector<int>& nums) { 4 const int n = nums.size(); 5 if (n == 0) {return false;} 6 vector<int> f(n, 0); //f[i] 代表第i个index是不是可达 7 f[0] = 1; 8 for (int i = 0; i < n; ++i) { 9 if (f[i]) { 10 const int k = nums[i]; 11 for (int j = 1; j <= k; ++j) { 12 if (i+j >= n) {break;} 13 f[i+j] = 1; 14 } 15 } 16 } 17 return f[n-1] == 1; 18 } 19 };
【122】Best Time to Buy and Sell Stock II (2018年11月26日,算法群)
这个题目股票系列里面说了,这里不重复写了。股票系列:https://www.cnblogs.com/zhangwanying/p/9360841.html
【134】Gas Station (2019年1月27日,谷歌tag)
一个圆形的跑道,上面有 N 个加油站,每个加油站能加的油是 gas[i],假设你的车能加无限的油量,从第 i 个加油站跑到第 i+1 个加油站所消耗的油是 cost[i], 返回从第几个加油站能够顺时针跑完一圈,如果从任意一个都不能跑完的话,就返回-1
题解:本题似乎用到了一个数学定理/方法。就是如果能跑完一圈的话,必定存在从一个点开始,任意的点上的油量都不会为负数。
1 class Solution { 2 public: 3 int canCompleteCircuit(vector<int>& gas, vector<int>& cost) { 4 int total = 0; 5 int sum = 0; 6 int ans = 0; 7 for(int i = 0; i < gas.size(); ++i){ 8 sum += gas[i] - cost[i]; 9 total += gas[i] - cost[i]; 10 if(sum < 0){ 11 ans = i+1; 12 sum = 0; 13 } 14 } 15 return total < 0? -1 : ans; 16 } 17 };
【135】Candy (2019年1月27日,谷歌tag)
每个小孩有一个 rating,你要给这些小孩发糖果,满足两条规则:规则1. 每个小孩至少一个糖果; 规则2. 如果一个小孩的rating比它的邻居高,那么他的糖果数量要比邻居多。问发完所有小孩的最少糖果数量。
题解:设置两个数组,一个front,从前往后应该发的糖果数量。一个back,表示从后往前应该发的糖果数量。final[i] = max(front[i], back[i]); O(N) with 2 pass
1 //每个小孩至少一个糖果, 2 //如果当前小孩的rating比它前一个小孩大的话,就是它前一个小孩的糖果数量+1 3 //如果当前小孩的rating比它后一个小孩大的话,就是它后一个小孩的糖果数量+1 4 class Solution { 5 public: 6 int candy(vector<int>& ratings) { 7 const int n = ratings.size(); 8 vector<int> front(n , 1), back(n, 1); 9 for (int i = 1; i < n; ++i) { 10 front[i] = ratings[i-1] < ratings[i] ? front[i-1] + 1 : 1; 11 } 12 int res = max(front[n-1], back[n-1]); 13 for (int i = n - 2; i >= 0; --i) { 14 back[i] = ratings[i] > ratings[i+1] ? back[i+1] + 1 : 1; 15 res += max(front[i], back[i]); 16 } 17 return res; 18 } 19 };
【253】Meeting Rooms II
题意是252的升级版,给了一个数组,数组里面的每个元素代表一个会议的开始时间和结束时间,问想安排下所有的会议,至少需要多少个会议室。
题解:这个题目在 sort 的分类里面说过,链接:https://www.cnblogs.com/zhangwanying/p/9914941.html
【316】Remove Duplicate Letters
【321】Create Maximum Number
【330】Patching Array
【358】Rearrange String k Distance Apart
【376】Wiggle Subsequence
【392】Is Subsequence
【402】Remove K Digits
【406】Queue Reconstruction by Height(2018年11月26日)
给了一个 people 的数组,数组里面每个元素是一个 pair (h, k) 代表 这个人身高是 h, 在排序好的队列中前面有 k 个人的升高大于等于 h。返回这个排序好的队列。
题解:有点类似于插入排序。我们先把people排序,排序按照身高降序,身高相同就按照 k 递增排序。然后做插入排序。对于排序好的people的每个元素 people[i],直接插入ret数组中的 people[i].second = k 这个位置上。
1 class Solution { 2 public: 3 vector<pair<int, int>> reconstructQueue(vector<pair<int, int>>& people) { 4 const int n = people.size(); 5 if (n == 0) {return people;} 6 sort(people.begin(), people.end(), cmp); 7 vector<pair<int, int>> ret; 8 for (int i = 0; i < people.size(); ++i) { 9 ret.insert(ret.begin() + people[i].second, people[i]); 10 } 11 return ret; 12 } 13 static bool cmp(const pair<int, int>& p1, const pair<int, int>& p2) { 14 if (p1.first == p2.first) { 15 return p1.second < p2.second; 16 } 17 return p1.first > p2.first; 18 } 19 };
【435】Non-overlapping Intervals (2018年11月26日)
这题应该见过了orz,莫名的熟悉。题意就是给了一堆线段,问这些线段在不重叠的前提下,最少要剔除几条满足这个线段不重叠的条件。
题解:最少剔除几条才能让所有线段不重叠,其实翻译过来,就是这些线段最多多少条不重叠。我们想这条直线上放尽可能多的线段,需要什么样的策略呢?就是第一条线段的末端的数值尽可能的小,这样后面能选择的空间才比较大。
所以先排序,按照线段末端从从小到大排序。然后贪心一个一个处理。(唯一一个注意点是线段的头尾都有可能是负数。)
1 /** 2 * Definition for an interval. 3 * struct Interval { 4 * int start; 5 * int end; 6 * Interval() : start(0), end(0) {} 7 * Interval(int s, int e) : start(s), end(e) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 int eraseOverlapIntervals(vector<Interval>& intervals) { 13 const int n = intervals.size(); 14 if (n == 0) {return n;} 15 sort(intervals.begin(), intervals.end(), cmp); 16 int cnt = 0; 17 int b = intervals[0].start; 18 for (auto inter : intervals) { 19 if (inter.start >= b) { 20 ++cnt; 21 b = inter.end; 22 } 23 } 24 return n - cnt; 25 } 26 static bool cmp(const Interval& p1, const Interval& p2) { 27 if (p1.end == p2.end) { 28 return p1.start > p2.start; 29 } 30 return p1.end < p2.end; 31 } 32 };
【452】Minimum Number of Arrows to Burst Balloons
【455】Assign Cookies
【484】Find Permutation
【502】IPO
【621】Task Scheduler
【630】Course Schedule III
【649】Dota2 Senate
【651】4 Keys Keyboard
【659】Split Array into Consecutive Subsequences
【714】Best Time to Buy and Sell Stock with Transaction Fee
【738】Monotone Increasing Digits
【757】Set Intersection Size At Least Two
【759】Employee Free Time
【763】Partition Labels (2018年11月27日)(这题第一遍的时候不会写,看了答案才会写。)
给了一个只含有小写字母的字符串,求这个字符串的能变成 partition label 的所有子串的长度(partition的越多越好)。能变成 partition label 的条件是,一个label里面含有的字母不能在其他label里面含有。
题解:我们用一个 map 记录每个字母最后一次出现的下标。然后用两个变量, start 和 end 表示当前 label 的开始和截止位置。遍历整个字符串,更新 end = max(mp[S[i]], end), 当我们发现 i == end 的时候,这个时候就是这个 label 结束了。
1 //本题第一遍的时候不会做看了答案。 2 class Solution { 3 public: 4 vector<int> partitionLabels(string S) { 5 const int n = S.size(); 6 unordered_map<char, int> mp; //record the last pos of c appear in S 7 for (int i = 0; i < n; ++i) { 8 mp[S[i]] = i; 9 } 10 int start = 0, end = 0; 11 vector<int> ret; 12 for (int i = 0; i < n; ++i) { 13 end = max(mp[S[i]], end); 14 if (end == i) { 15 ret.push_back(end - start + 1); 16 start = i + 1; 17 } 18 } 19 return ret; 20 } 21 };
【765】Couples Holding Hands
【767】Reorganize String
【842】Split Array into Fibonacci Sequence
【860】Lemonade Change
【861】Score After Flipping Matrix
【870】Advantage Shuffle
【874】Walking Robot Simulation
【881】Boats to Save People
原文地址:https://www.cnblogs.com/zhangwanying/p/9886719.html