156.上下翻转二叉树
要求:如图所示看箭头
思路:迭代递归都行
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution1 {
public:
TreeNode* upsideDownBinaryTree(TreeNode* root) {
if (!root || !root->left) {
return root;
}
TreeNode* left = root->left;
TreeNode* right = root->right;
TreeNode* flippedLeft = upsideDownBinaryTree(left);
left->left = right; // turn original right into left
left->right = root; // turn original root into right
root->left = nullptr;
root->right = nullptr;
return flippedLeft;
}
};
class Solution {
public:
TreeNode* upsideDownBinaryTree(TreeNode* root) {
TreeNode* cur = root;
TreeNode* pre = nullptr;
TreeNode* tmp = nullptr;
while (cur) {
auto next = cur->left;
cur->left = tmp; // copy original right to left
tmp = cur->right; // save next level original right
cur->right = pre; // copy original root to right
pre = cur; // save cur root, i.e: next level left
cur = next;
}
return pre;
}
};
157.用 Read4 读取 N 个字符
要求:read4能读最多4个字符到buf并返回读了几个。实现read调用read4读n个字符,返回实际读了几个,buf够长
/**
* The read4 API is defined in the parent class Reader4.
* int read4(char *buf4);
*/
class Solution {
public:
/**
* @param buf Destination buffer
* @param n Number of characters to read
* @return The number of actual characters read
*/
int read(char *buf, int n) {
int res = 0;
for (int i = 0; i < n; i += 4)
{
res += read4(buf); //指针后移
buf += 4;
}
return min(res, n);
}
};
158.用 Read4 读取 N 个字符 II
跟上题区别是要多次读取,要把buf存下来
/**
* The read4 API is defined in the parent class Reader4.
* int read4(char *buf4);
*/
class Solution {
public:
char *buf4 = new char[4];
int buf4Index = 0;
int buf4Size = 0;
int read(char *buf, int n) {
int index = 0;
while(index<n){
while(buf4Index<buf4Size && index<n){
buf[index++] = buf4[buf4Index++];
}
if(index<n){
buf4Size = read4(buf4);
buf4Index = 0;
if(buf4Size==0) break;
}
}
return index;
}
};
159.至多包含两个不同字符的最长子串
rt,滑动窗口
class Solution {
public:
int lengthOfLongestSubstringTwoDistinct(string s) {
if(s.size()<=2)
return s.size();
int l=0,r=0,preIndex=-1,maxLength=0;
while(r<s.size()-1){
r++;
if(s[r]==s[r-1])
maxLength=max(maxLength,r-l+1);
else if(preIndex==-1 || s[r]==s[preIndex]){
preIndex=r-1;
maxLength=max(maxLength,r-l+1);
}else{
l=preIndex+1;
preIndex=r-1;
}
}
return maxLength;
}
};
161.相隔为 1 的编辑距离
一个字符串由另一个插/换/删1个字符得到,注意这里除了那个字符外两串顺序一样
class Solution {
public:
bool isOneEditDistance(string s, string t) {
int ns=s.length(),nt=t.length();
if(ns>nt)
return isOneEditDistance(t,s);
if(nt-ns>1)return 0;
int replace=0;
for(int i=0;i<ns;i++){
if(s[i]!=t[i]){
if(nt!=ns)
return (s.substr(i)==t.substr(i+1));
else return (i==ns-1)||(s.substr(i+1)==t.substr(i+1));
}
}
return nt!=ns;
}
};
163.缺失的区间
输入: nums = [0, 1, 3, 50, 75], lower = 0 和 upper = 99,
输出: [“2”, “4->49”, “51->74”, “76->99”]
class Solution {
public:
vector<string> findMissingRanges(vector<int>& nums, int lower, int upper) {
long l = lower;
vector<string> ans;
for(int i = 0; i < nums.size(); ++i)
{
if(l == nums[i])
l++;//相等,我跳过你
else if(l < nums[i])
{ //有空缺
if(l < nums[i]-1)//大于1
ans.push_back(to_string(l)+"->"+to_string(nums[i]-1));
else if(l == nums[i]-1)//等于1
ans.push_back(to_string(l));
l = long(nums[i])+1;//更新l到nums[i]下一个数
// [2147483647]
// 0
// 2147483647
}
}
if(l < upper)
ans.push_back(to_string(l)+"->"+to_string(upper));
else if(l==upper)
ans.push_back(to_string(l));
return ans;
}
};
170.两数之和 III - 数据结构设计
存数并判断是否有两数之和为target,要用哈希存频数
class TwoSum
{
public:
unordered_map<long long,int> dic;
/** Initialize your data structure here. */
TwoSum()
{
}
/** Add the number to an internal data structure.. */
void add(int number)
{
if (dic.count(number) != 0)
dic[number] ++;
else
dic[number] = 1;
}
/** Find if there exists any pair of numbers which sum is equal to the value. */
bool find(int value)
{
for (auto [x, freq]: dic)
{
long long y = (long long)value - x;
if (x == y)
{
if (dic[x] >= 2)
return true;
}
else
{
if (dic.count(y) != 0)
{
return true;
}
}
}
return false;
}
};
/**
* Your TwoSum object will be instantiated and called as such:
* TwoSum* obj = new TwoSum();
* obj->add(number);
* bool param_2 = obj->find(value);
*/
186.翻转字符串里的单词 II
输入: [“t”,“h”,“e”," “,“s”,“k”,“y”,” “,“i”,“s”,” “,“b”,“l”,“u”,“e”]
输出: [“b”,“l”,“u”,“e”,” “,“i”,“s”,” “,“s”,“k”,“y”,” ",“t”,“h”,“e”]
class Solution {
public:
void reverseWords(vector<char>& s) {
int left = 0;
int right = 0;
int len = s.size();
while (right < len) {
if (s[right] == ' ') {
Swap(s, left, right - 1);
right++;
left = right;
} else {
right++;
}
}
Swap(s, left, len - 1);
Swap(s, 0, len - 1);
}
void Swap(vector<char>& s, int left, int right) {
char temp;
while (left < right) {
temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
}
};
253.会议室 II
给你一个会议时间安排的数组 intervals ,每个会议时间都会包括开始和结束的时间 intervals[i] = [starti, endi] ,返回 所需会议室的最小数量 。就是最多的重叠的区间个数。优先队列最大size,或者模拟开会时间加1结束减1取最大值
class Solution{
public:
int minMeetingRooms(vector<vector<int>>& intervals){
int N=intervals.size();
sort(intervals.begin(),intervals.end());
priority_queue<int,vector<int>,greater<int>>que;
que.push(intervals[0][1]);
int res=1;
for(int i=1;i<N;i++){
if(intervals[i][0]>=que.top()){
que.pop();
que.push(intervals[i][1]);
}
else{
que.push(intervals[i][1]);
}
int T=que.size();
res=max(res,T);
}
return res;
}
};
class Solution { // 排序+遍历
public:
struct cmp { // 排序优先级:会议时间升序 > 相等时间先结束后开始
bool operator()( const pair<int, int> & p1, const pair<int, int> & p2 ) {
if (p1.first == p2.first) return p1.second < p2.second; // 会议时间相同,先结束后开始
return p1.first < p2.first; // 按会议时间升序排序
}
};
int minMeetingRooms(vector<vector<int>>& intervals) {
int n = intervals.size();
if (n < 2) return n;
vector<pair<int, int>> times;
for (auto & inter : intervals) {
times.emplace_back( make_pair(inter[0], 1) ); // 会议开始,会议室+1
times.emplace_back( make_pair(inter[1], -1) ); // 会议结束,会议室-1
}
sort(times.begin(), times.end(), cmp()); // 排序
int works = 0, ans = 1;
for (auto & t : times) {
works += t.second; // 此时开会的会议室数量
ans = max(ans, works); // 记录最多数量
}
return ans;
}
};
251.展开二维向量
二维vector一个个值输出。y是记录某个一维vector里访问到第几个了
// In the following x is a pointer to pointer, *x is an pointer to array v[i] above
class Vector2D {
public:
Vector2D(vector<vector<int>>& vec) {
x = vec.begin();
end = vec.end();
}
void moveToNext() {
while (x != end && y == (*x).size()) {
x++;
y = 0;
}
}
int next() {
moveToNext();
return (*x)[y++];
}
bool hasNext() {
moveToNext();
return x != end && y < (*x).size();
}
private:
int y = 0;
vector<vector<int>>::iterator x;
vector<vector<int>>::iterator end;
};
/**
* Your Vector2D object will be instantiated and called as such:
* Vector2D* obj = new Vector2D(vec);
* int param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/
269.火星词典
字符串数组按新的字符大小规则排序了,如果合理的话输出字符大小顺序
可以根据单词按字符建图拓扑排序看是否有环
class Solution {
public:
const int VISITING = 1, VISITED = 2;
unordered_map<char, vector<char>> edges;
unordered_map<char, int> states;
bool valid = true;
string order;
int index;
string alienOrder(vector<string>& words) {
int length = words.size();
for (string & word : words) {
int wordLength = word.size();
for (int j = 0; j < wordLength; j++) {
char c = word[j];
if (!edges.count(c)) {
edges[c] = vector<char>();
}
}
}
for (int i = 1; i < length && valid; i++) {
addEdge(words[i - 1], words[i]);
}
order = string(edges.size(), ' ');
index = edges.size() - 1;
for (auto [u, _] : edges) {
if (!states.count(u)) {
dfs(u);
}
}
if (!valid) {
return "";
}
return order;
}
void addEdge(string before, string after) {
int length1 = before.size(), length2 = after.size();
int length = min(length1, length2);
int index = 0;
while (index < length) {
char c1 = before[index], c2 = after[index];
if (c1 != c2) {
edges[c1].emplace_back(c2);
break;
}
index++;
}
if (index == length && length1 > length2) {
valid = false;
}
}
void dfs(char u) {
states[u] = VISITING;
for (char v : edges[u]) {
if (!states.count(v)) {
dfs(v);
if (!valid) {
return;
}
} else if (states[v] == VISITING) {
valid = false;
return;
}
}
states[u] = VISITED;
order[index] = u;
index--;
}
};
class Solution {
public:
unordered_map<char, vector<char>> edges;
unordered_map<char, int> indegrees;
bool valid = true;
string alienOrder(vector<string>& words) {
int length = words.size();
for (auto word : words) {
int wordLength = word.size();
for (int j = 0; j < wordLength; j++) {
char c = word[j];
if (!edges.count(c)) {
edges[c] = vector<char>();
}
}
}
for (int i = 1; i < length && valid; i++) {
addEdge(words[i - 1], words[i]);
}
if (!valid) {
return "";
}
queue<char> qu;
for (auto [u, _] : edges) {
if (!indegrees.count(u)) {
qu.emplace(u);
}
}
string order;
while (!qu.empty()) {
char u = qu.front();
qu.pop();
order.push_back(u);
for (char v : edges[u]) {
indegrees[v]--;
if (indegrees[v] == 0) {
qu.emplace(v);
}
}
}
return order.size() == edges.size() ? order : "";
}
void addEdge(string before, string after) {
int length1 = before.size(), length2 = after.size();
int length = min(length1, length2);
int index = 0;
while (index < length) {
char c1 = before[index], c2 = after[index];
if (c1 != c2) {
edges[c1].emplace_back(c2);
indegrees[c2] += 1;
break;
}
index++;
}
if (index == length && length1 > length2) {
valid = false;
}
}
};
277.搜寻名人
名人定义是其他人都认识他但他不认识其他人,编号是0-n-1,可以调用knows函数获取a是否认识b。如果 knows(i,j) 为ture,说明i不可能是名人。如果 knows(i,j) 为false, 说明j不可能是名人。也就说说任意两人相互比较总能淘汰一个人。
/* The knows API is defined for you.
bool knows(int a, int b); */
// Forward declaration of the knows API.
class Solution {
public:
int findCelebrity(int n) {
int result = 0;
for (int i = 1; i < n; ++i) {
if (knows(result, i)) {
result = i;
}
}
for (int i = 0; i < n; ++i) {//检查是否符合名人条件
if (result == i) continue;
if (knows(result, i) || !knows(i, result)) return -1;
}
return result;
}
};
285.二叉搜索树中的中序后继
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
TreeNode* ans=nullptr;
// 若p有右子树,右子树最左的叶子结点为p的后续结点
if(p->right){
ans=p->right;
while(ans->left)
ans=ans->left;
}
// 若p没有右子树,考虑二叉搜索树的性质
else{
// @@ 从根结点到p结点的路径中,比p大的、最靠近p的结点即为p的后序结点 @@
TreeNode *cur=root;
while(cur!=p){
if(cur->val>p->val){
ans=cur; // 不断记录最新的比p大的结点
cur=cur->left;
}
else
cur=cur->right;
}
}
return ans;
}
};
308.二维区域和检索 - 可变
矩阵求一块的和,用每一行的前缀和做
class NumMatrix
{
public:
int b[404][404];
vector<vector<int>> a;
int n, m;
NumMatrix(vector<vector<int>> &a) : a(a)
{
n = a.size(), m = a[0].size();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
{
b[i][j] = b[i][j - 1] + a[i - 1][j - 1];
}
}
void update(int l, int r, int v)
{
a[l][r] = v;
for (int j = r + 1; j <= m; ++j)
b[l + 1][j] = b[l + 1][j - 1] + a[l][j - 1];
}
int sumRegion(int x, int y, int l, int r)
{
int sum = 0;
for (int i = x + 1; i <= l + 1; ++i)
{
sum += b[i][r + 1] - b[i][y];
}
return sum;
}
};
/**
* Your NumMatrix object will be instantiated and called as such:
* NumMatrix* obj = new NumMatrix(matrix);
* obj->update(row,col,val);
* int param_2 = obj->sumRegion(row1,col1,row2,col2);
*/
340.至多包含 K 个不同字符的最长子串
哈希表,滑动窗口
class Solution {
public:
int lengthOfLongestSubstringKDistinct(string s, int k) {
unordered_map<char,int> map;
if(k==0){return 0;}
int n = s.size();
int ans =0;
for(int l=0,r=0;r<n;r++){
map[s[r]]++;
while(map.size()>k){
map[s[l]]--;
if(map[s[l]]==0){map.erase(s[l]);}
l++;
}
ans = max(ans,r-l+1);
}
return ans;
}
};
348.设计井字棋
class TicTacToe {
vector<int> r, c, q;
int n;
public:
TicTacToe(int n) : r(n), c(n), q(2), n(n){}
int move(int row, int col, int player) {
if(player == 1 && (++r[row] == n || ++c[col] == n || row == col && ++q[0] == n || row + col == n - 1 && ++q[1] == n) ||
player == 2 && (--r[row] == -n || --c[col] == -n || row == col && --q[0] == -n || row + col == n - 1 && --q[1] == -n)) return player;
return 0;
}
};
/**
* Your TicTacToe object will be instantiated and called as such:
* TicTacToe* obj = new TicTacToe(n);
* int param_1 = obj->move(row,col,player);
*/