剑指 Offer 56 - I. 数组中数字出现的次数 中等
class Solution {
public:
vector<int> singleNumbers(vector<int>& nums) {
if (nums.empty()) return {};
int res = 0;
for (int num:nums) res ^= num;
int temp = 1;
while ((temp & res) == 0)
temp <<= 1;
int num1=0, num2=0;
for (int num:nums){
if ((temp & num) == 0)//注意&的优先级
num1 ^= num;
else
num2 ^= num;
}
return {num1, num2};
}
};
剑指 Offer 64. 求1+2+…+n 中等
class Solution {
int sum = 0;
int Nums(int n) {
sum += n;
return n && sumNums(n-1);
}
public:
int sumNums(int n) {
Nums(n);
return sum;
}
};
剑指 Offer 47. 礼物的最大价值 中等
记忆化搜索用数组更好理解,二维数组
class Solution {
public:
vector<vector<int>> memo;
int dfs(vector<vector<int>>& grid, int i, int j){
if(i<0 || j<0)
return 0;
if(memo[i][j]!=-1)
return memo[i][j];//查询记录 发现就返回
memo[i][j] = max(dfs(grid, i-1, j), dfs(grid, i, j-1)) + grid[i][j];
return memo[i][j];
}
int maxValue(vector<vector<int>>& grid) {
memo = vector<vector<int>>(grid.size(),vector<int>(grid[0].size(), -1));
return dfs(grid,grid.size()-1,grid[0].size()-1);
}
};
剑指 Offer 58 - I. 翻转单词顺序 简单
仔细体味这段代码
class Solution {
public:
string reverseWords(string s) {
if(s.empty())return s;
int len = 0;
string ans = "";
for(int m = s.size()-1; m >=0; m--){//" hello world! "
if(s[m]==' ' && len!=0){
ans += s.substr(m+1,len)+ " ";
len = 0;
continue;
}
if(s[m]!= ' ')len++;
}
if(len !=0) ans += s.substr(0,len) + " ";
if(ans.size()>0)ans.erase(ans.size()-1,1);
return ans;
}
};
剑指 Offer 49. 丑数 中等
下面是动态规划讲解
https://leetcode-cn.com/problems/chou-shu-lcof/solution/chou-shu-ii-qing-xi-de-tui-dao-si-lu-by-mrsate/
class Solution {
public:
int nthUglyNumber(int n) {
vector<int> dp(n, 0); dp[0] = 1;
int p2=0, p3=0, p5=0;
for (int i=1; i<n; i++){
dp[i] = min(dp[p2]*2, min(dp[p3]*3, dp[p5]*5));
if (dp[i] == dp[p2]*2) p2++;
if (dp[i] == dp[p3]*3) p3++;
if (dp[i] == dp[p5]*5) p5++;
}
return dp[n-1];
}
};
剑指 Offer 59 - I. 滑动窗口的最大值 简单
维护一个双端队列
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;
if (nums.size() < k) return {};
deque<int> que;
for (int i=0; i<nums.size(); i++){
while (!que.empty() && nums[i]>que.back())
que.pop_back();
que.push_back(nums[i]);
if (i >= k-1)
res.push_back(que.front());
if (i >= k-1 && que.front() == nums[i-k+1])
que.pop_front();
}
return res;
}
};
剑指 Offer 53 - II. 0~n-1中缺失的数字 简单
二分法,这个通过动态分析去做,遵循开闭原则
class Solution {
public:
int missingNumber(vector<int>& nums) {
int left=0, right=nums.size();
while (left < right){
int mid = (left + right) / 2;
if (mid == nums[mid])
left = mid + 1;
else if (mid != nums[mid])
right = mid;
}
return left;
}
};
剑指 Offer 61. 扑克牌中的顺子 简单
class Solution {
public:
bool isStraight(vector<int>& nums) {
sort(nums.begin(), nums.end());
int start=0;
for (int i=0; i<nums.size(); i++)
if (nums[i] != 0){
start = i;
break;
}
for (int j=start; j<nums.size()-1; j++)
if (nums[j] == nums[j+1])
return false;
return (nums[nums.size()-1]-nums[start] <= 4);
}
};
剑指 Offer 31. 栈的压入、弹出序列 中等
class Solution {
public:
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
if (pushed.empty())
return true;
stack<int> stk; int j=0;
for (int i=0; i<pushed.size(); i++){
stk.push(pushed[i]);
while (!stk.empty() && stk.top() == popped[j]){
stk.pop();
j++;
}
}
return stk.empty();
}
};
剑指 Offer 34. 二叉树中和为某一值的路径 中等
记住这种类型的题,大概就是这个模板
class Solution {
vector<vector<int>> res;
void path(TreeNode* root, int sum, vector<int> temp){
if (root == NULL)
return;
sum -= root->val; temp.push_back(root->val);
if (sum == 0 && root->left==NULL && root->right==NULL)
res.push_back(temp);
path(root->left, sum, temp);
path(root->right, sum, temp);
}
public:
vector<vector<int>> pathSum(TreeNode* root, int sum) {
vector<int> temp;
path(root, sum, temp);
return res;
}
};
剑指 Offer 45. 把数组排成最小的数 中等
这道题转换为字符串比较大小
class Solution {
public:
string minNumber(vector<int>& nums) {
auto cmp = [](const string a, const string b){return a+b < b+a;};
vector<string> temp;
for (int i:nums)
temp.push_back(to_string(i));
sort(temp.begin(), temp.end(), cmp);
string res("");
for (string s:temp)
res += s;
return res;
}
};
剑指 Offer 14- I. 剪绳子 中等
贪心法
class Solution {
public:
int cuttingRope(int n) {
if (n < 4) return n-1;
int res = 0;
int num = n / 3;
int yu = n % 3;
if (yu == 1)
return pow(3, num-1)*4;
if (yu == 2)
return pow(3, num)*2;
if (yu == 0)
return pow(3, num);
return n;
}
};
class Solution {
public:
int cuttingRope(int n) {
if(n<=3) return n-1;
int mod = 1000000007;
long long res = 1;
while(n > 4 ){
res *= 3;
res %= mod;
n -= 3;
}
res = res * n % mod;
return res;
}
};
剑指 Offer 38. 字符串的排列 中等
回溯避重模板
class Solution {
vector<string> res;
void backTrack(string s, string& temp, vector<bool>& visit){
if (s.length() == temp.length()){
res.push_back(temp);
return;
}
for (int i=0; i<s.length(); i++){
if (visit[i])
continue;
if (i > 0 && s[i] == s[i-1] && visit[i-1])
continue;
visit[i] = true;
temp += s[i];
backTrack(s, temp, visit);
visit[i] = false;
temp = temp.substr(0, temp.length()-1);
}
}
public:
vector<string> permutation(string s) {
vector<bool> visit(s.length(), false);
string temp("");
sort(s.begin(), s.end());//先排序,要记住这里
backTrack(s, temp, visit);
return res;
}
};
剑指 Offer 46. 把数字翻译成字符串 中等
class Solution {
public:
int translateNum(int num) {
string s = to_string(num);
vector<int> arr(s.size() + 1, 1);
arr[0] = 1;
arr[1] = 1;
for(int i = 2; i <= s.size(); i++){
auto a = s.substr(i-2, 2);
if(a >= "10" && a <= "25")
arr[i] = arr[i - 1] + arr[i - 2];
else
arr[i] = arr[i - 1];
}
return arr[s.size()];
}
};
剑指 Offer 13. 机器人的运动范围 中等
题不难,麻烦认真读题
class Solution {
int dir[2][2] = {1,0,0,1};
int BFS(vector<vector<int>>& matrix, int k){
queue<pair<int,int>> que; que.push(pair<int,int>(0,0));
int res = 1; matrix[0][0] = 1;
while (!que.empty()){
auto temp = que.front();
que.pop();
for (int i=0; i<2; i++){
int x = temp.first + dir[i][0];
int y = temp.second + dir[i][1];
if (x >= matrix.size() || y >= matrix[0].size() || x/10+x%10+y/10+y%10>k)
continue;
if (matrix[x][y] == 1){
matrix[x][y] = 0;
res++;
que.push(pair<int,int>(x,y));
}
}
}
return res;
}
public:
int movingCount(int m, int n, int k) {
vector<vector<int>> matrix(m, vector<int>(n, 1));
return BFS(matrix, k);
}
};
class Solution {
int res = 0;
void DFS(vector<vector<int>>& matrix, int i, int j, int k){
if (i<0 || j<0 || i>=matrix.size() || j>=matrix[0].size() || i/10+i%10+j/10+j%10>k)
return;
if (matrix[i][j] == 1){
matrix[i][j] = 0;
res += 1;
DFS(matrix,i-1,j,k);
DFS(matrix,i,j-1,k);
DFS(matrix,i+1,j,k);
DFS(matrix,i,j+1,k);
}
}
public:
int movingCount(int m, int n, int k) {
vector<vector<int>> matrix(m, vector<int>(n, 1));
DFS(matrix, 0, 0, k);
return res;
}
};
剑指 Offer 26. 树的子结构 中等
每次解题发现按照思路写出来的程序还是不对的时候,就举个例子,来顺着程序看步骤对不对,这样就很容易发现问题
class Solution {
bool SubStructure(TreeNode* A, TreeNode* B){
if (B == NULL)//注意判断A、B的先后顺序
return true;
if (A == NULL)
return false;
if (A->val != B->val)
return false;
return SubStructure(A->left, B->left) && SubStructure(A->right, B->right);
}
public:
bool isSubStructure(TreeNode* A, TreeNode* B) {
if (A == NULL || B == NULL)
return false;
return SubStructure(A,B) || isSubStructure(A->left,B) || isSubStructure(A->right,B);
}
};
剑指 Offer 12. 矩阵中的路径 中等
记住这个模板
class Solution {
bool DFS(vector<vector<char>>& board, string word, string& temp, int i, int j){
if (i<0 || j<0 || i>=board.size() || j>=board[0].size())
return false;
bool a, b, c, d;
if (board[i][j] != '0'){
auto s = board[i][j];
temp += s;
board[i][j] = '0';
if (temp.length() == word.length() && temp == word)
return true;
a = DFS(board,word,temp,i-1,j);
b = DFS(board,word,temp,i,j-1);
c = DFS(board,word,temp,i+1,j);
d = DFS(board,word,temp,i,j+1);
temp = temp.substr(0,temp.length()-1);
board[i][j] = s;//这里修改回去
}
return a || b || c || d;
}
public:
bool exist(vector<vector<char>>& board, string word) {
bool flag = false;
for (int i=0; i<board.size(); i++){
for (int j=0; j<board[0].size(); j++){
string temp("");
flag |= DFS(board,word,temp,i,j);
}
}
return flag;
}
};
剑指 Offer 67. 把字符串转换成整数 中等
class Solution {
public:
int strToInt(string str) {
if (str.empty()) return 0;
while (str[0] == ' ') str = str.substr(1);
int flag = 1;
if (str[0] == '-') {str = str.substr(1); flag = -1;}
else if (str[0] == '+') str = str.substr(1);
long long res = 0;
for (int i=0; i<str.length(); i++){
if (!isdigit(str[i]))
break;
res += str[i]-'0';
if (res >= INT_MAX && flag == 1) return INT_MAX;
if (res-1 >= INT_MAX && flag == -1) return INT_MIN;
res *= 10;
}
return res/10*flag;
}
};
数据流的中位数 困难
class MedianFinder {
vector<int> nums;
public:
/** initialize your data structure here. */
MedianFinder() {
}
void addNum(int num) {
if (nums.empty()){
nums.push_back(num);
return;
}
int left=0, right=nums.size();
while (left < right){
int mid = (left + right) / 2;
if (nums[mid] < num)
left = mid+1;
else if (nums[mid] > num)
right = mid;
else if (nums[mid] == num){
left = mid;
break;
}//1 2
}
nums.insert(nums.begin()+left, num);
}
double findMedian() {
if (nums.size() % 2 == 1)
return nums[nums.size()/2];
else
return (nums[nums.size()/2]+nums[nums.size()/2-1])/2.0;
}
};