学习链接:
1.分割回文串
题目来源:131.分割回文串
题解:
class Solution {
public:
vector<vector<int>> f;
vector<vector<string>> ret;
vector<string> ans;
int n;
vector<vector<string>> partition(string s) {
n=s.size();
f=vector<vector<int>>(n,vector<int>(n,true));
for(int i=n-1;i>=0;i--){
for(int j=i+1;j<n;j++){
f[i][j]=f[i+1][j-1]&&(s[i]==s[j]);
}
}
dfs(s,0);
return ret;
}
void dfs(string s,int i){
if(i==n){
ret.push_back(ans);
return;
}
for(int j=i;j<n;j++)
{
if(f[i][j]){
ans.push_back(s.substr(i,j-i+1));
dfs(s,j+1);
ans.pop_back();
}
}
}
};
2.组合总数
题目来源:39.组合总数
题解:
class Solution {
public:
vector<vector<int>> ret;
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<int> ans;
int n=candidates.size();
sort(candidates.begin(),candidates.end());
backtrack(candidates,0,n,ans,target);
return ret;
}
void backtrack(vector<int>& candidates,int begin,int len,vector<int>& ans, int target){
if(target==0)
{
ret.push_back(ans);
return;
}
for(int i=begin;i<len;i++){
if(target-candidates[i]<0)
return;
ans.push_back(candidates[i]);
backtrack(candidates,i,len,ans,target-candidates[i]);
ans.pop_back();
}
}
};
3.划分为k个相等的子集
题目来源:
698. 划分为k个相等的子集
题解:
class Solution {
public:
bool canPartitionKSubsets(vector<int>& nums, int k) {
int n=nums.size(),sum=0;
for(int i=0;i<n;i++)
sum+=nums[i];
if(sum%k!=0)
return false;
sum/=k;
vector<int> bucket(k);
sort(nums.begin(),nums.end(),greater<int>());//按降序排序后,效率更好!!!
return backtrack(nums,0,bucket,k,sum);
}
bool backtrack(vector<int>& nums,int index,vector<int>& bucket,int k,int sum){
if(index==nums.size()){
return true;
}
for(int i=0;i<k;i++){
if(i>0&&bucket[i]==bucket[i-1]) continue;//去掉重复计算的情况!!能够优化效率!!
if(bucket[i]+nums[index]>sum) continue;
bucket[i]+=nums[index];
if(backtrack(nums,index+1,bucket,k,sum)) return true;
bucket[i]-=nums[index];
}
return false;
}
};
4.子集
题目来源:78.子集
题解:
class Solution {
public:
vector<vector<int>> res;
vector<vector<int>> subsets(vector<int>& nums) {
int n=nums.size();
if(n==0) return res;
vector<int> ans;
backtrack(nums,ans,0);
return res;
}
void backtrack(vector<int>& nums,vector<int>& ans,int index){
if(index==nums.size()){
res.push_back(ans);
return;
}
ans.push_back(nums[index]);
backtrack(nums,ans,index+1);
ans.pop_back();
backtrack(nums,ans,index+1);
}
};
5.单词拆分II*******
题目来源:140.单词拆分II
题解:
//回溯法
class Solution {
public:
unordered_set<string> wordset;
vector<string> ans;
vector<string> wordBreak(string s, vector<string>& wordDict) {
for(auto word:wordDict)
wordset.insert(word);
string str="";
backtrack(s,wordset,0,str);
return ans;
}
void backtrack(string s,unordered_set<string>& st,int idx,string track){
int n=s.size();
if(idx==n){
ans.push_back(track);
return;
}
for(int i=idx;i<n;i++){
string word=s.substr(idx,i-idx+1);
if(st.find(word)!=st.end()){
int pos=track.size();
if(pos>0)
track+=" ";
track+=word;
backtrack(s,st,i+1,track);
track.erase(track.begin()+pos,track.end());
}
}
}
};
//动态规划
class Solution {
private:
unordered_map<int, vector<string>> ans;
unordered_set<string> wordSet;
public:
vector<string> wordBreak(string s, vector<string>& wordDict) {
//wordSet = unordered_set(wordDict.begin(), wordDict.end());
for(auto word:wordDict)
wordSet.insert(word);
backtrack(s, 0);
return ans[0];
}
void backtrack(const string& s, int index) {
if (!ans.count(index)) {
if (index == s.size()) {
ans[index] = {""};
return;
}
ans[index] = {};
for (int i = index + 1; i <= s.size(); ++i) {
string word = s.substr(index, i - index);
if (wordSet.count(word)) {
backtrack(s, i);
for (const string& succ: ans[i]) {
ans[index].push_back(succ.empty() ? word : word + " " + succ);
}
}
}
}
}
};
6.复原IP地址
题目来源:93. 复原 IP 地址
题解:
class Solution {
public:
vector<string> ans;
vector<int> segment;
vector<string> restoreIpAddresses(string s) {
segment.resize(4);
backtrack(s,0,0);
return ans;
}
void backtrack(string s,int segidx,int segstart){
if(segidx==4){
if(segstart==s.size()){
string addr;
for(int i=0;i<3;i++){
addr+=to_string(segment[i]);
addr+=".";
}
addr+=to_string(segment[3]);
ans.push_back(addr);
}
return;
}
if(segstart==s.size())
return;
if(s[segstart]=='0'){
segment[segidx]=0;
backtrack(s,segidx+1,segstart+1);
}
int addr=0;
for(int i=segstart;i<s.size();i++){
addr=addr*10+(s[i]-'0');
if(addr>0&&addr<=255){
segment[segidx]=addr;
backtrack(s,segidx+1,i+1);
}
else
break;
}
}
};
7.递增子序列
题目来源:491. 递增子序列
题解:
class Solution {
public:
vector<int> temp;
vector<vector<int>> ans;
void dfs(int cur, int last, vector<int>& nums) {
if (cur == nums.size()) {
if (temp.size() >= 2) {
ans.push_back(temp);
}
return;
}
if (nums[cur] >= last) {
temp.push_back(nums[cur]);
dfs(cur + 1, nums[cur], nums);
temp.pop_back();
}
if (nums[cur] != last) {
dfs(cur + 1, last, nums);
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
dfs(0, INT_MIN, nums);
return ans;
}
};
8. 机器人的运动范围
题目来源:剑指 Offer 13. 机器人的运动范围
题解:
class Solution {
public:
int get(int x){
int res=0;
while(x){
res=res+(x%10);
x/=10;
}
return res;
}
int movingCount(int m, int n, int k) {
if(k==0) return 1;
vector<vector<int>> vis(m,vector<int>(n,0));
int ans=1;
vis[0][0]=1;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if((i==0&&j==0)||get(i)+get(j)>k) continue;
if (i - 1 >= 0) vis[i][j] |= vis[i - 1][j];
if (j - 1 >= 0) vis[i][j] |= vis[i][j - 1];
ans += vis[i][j];
}
}
return ans;
}
};
//解法2
class Solution {
public:
int get(int x){
int res=0;
while(x){
res=res+(x%10);
x/=10;
}
return res;
}
int movingCount(int m, int n, int k) {
if(k==0) return 1;
queue<pair<int,int>> q;
vector<vector<int>> vis(m,vector<int>(n,0));
int dx[2] = {0, 1};
int dy[2] = {1, 0};
q.push({0,0});
vis[0][0]=1;
int ans=1;
while(!q.empty()){
auto [x,y]=q.front();
q.pop();
for (int i = 0; i < 2; ++i) {
int tx = dx[i] + x;
int ty = dy[i] + y;
if (tx < 0 || tx >= m || ty < 0 || ty >= n || vis[tx][ty] || get(tx) + get(ty) > k) continue;
q.push(make_pair(tx, ty));
vis[tx][ty] = 1;
ans++;
}
}
return ans;
}
};
9.单词搜索*****
题目来源:79.单词搜索
class Solution {
public:
int m,n;
bool exist(vector<vector<char>>& board, string word) {
m=board.size(),n=board[0].size();
vector<vector<bool>> used(m,vector<bool>(n,false));
int len=word.size();
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(dfs(board,m,n,used,i,j,word,len,0))
return true;
}
}
return false;
}
int directions[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
bool dfs(vector<vector<char>>& board,int m,int n,vector<vector<bool>>& used,int i,int j,string& word,int len,int idx){
if(board[i][j]!=word[idx])
return false;
else if(idx==len-1)
return true;
used[i][j]=true;
bool result=false;
for (int sel = 0; sel < 4; sel++) {
int newi = i + directions[sel][0], newj = j + directions[sel][1];
if (newi >= 0 && newi < m && newj >= 0 && newj < n) {
if (!used[newi][newj]) {
bool flag = dfs(board,m,n,used,newi,newj,word,len, idx+1);
if (flag) {
result = true;
break;
}
}
}
}
used[i][j] = false;
return result;
}
};
10.打开转盘锁
题目来源:752.打开转盘锁
剑指 Offer II 109. 开密码锁
题解:
class Solution {
public:
string plusone(string s,int j){
if(s[j]=='9')
s[j]='0';
else
s[j]+=1;
return s;
}
string minusone(string s,int j){
if(s[j]=='0')
s[j]='9';
else
s[j]-=1;
return s;
}
int openLock(vector<string>& deadends, string target) {
unordered_set<string> deads;
for(auto& s:deadends){
deads.insert(s);
}
unordered_set<string> vis;
queue<string> q;
int step=0;
q.push("0000");
vis.insert("0000");
while(!q.empty()){
int sz=q.size();
for(int i=0;i<sz;i++){
string cur=q.front();
q.pop();
if(deads.count(cur))
continue;
if(cur==target)
return step;
for(int j=0;j<4;j++){
string up=plusone(cur,j);
if(!vis.count(up)){
q.push(up);
vis.insert(up);
}
string down=minusone(cur,j);
if(!vis.count(down)){
q.push(down);
vis.insert(down);
}
}
}
step++;
}
return -1;
}
};
//双向BFS
class Solution {
public:
string plusone(string s,int j){
if(s[j]=='9')
s[j]='0';
else
s[j]+=1;
return s;
}
string minusone(string s,int j){
if(s[j]=='0')
s[j]='9';
else
s[j]-=1;
return s;
}
int openLock(vector<string>& deadends, string target) {
unordered_set<string> deads(deadends.begin(),deadends.end());
unordered_set<string> q1,q2,vis;
int step=0;
q1.insert("0000");
q2.insert(target);
while(!q1.empty()&&!q2.empty()){
unordered_set<string> temp;
for(auto cur:q1){
if(deads.count(cur))
continue;
if(q2.count(cur))
return step;
vis.insert(cur);
for(int j=0;j<4;j++){
string up=plusone(cur,j);
if(!vis.count(up))
temp.insert(up);
string down=minusone(cur,j);
if(!vis.count(down))
temp.insert(down);
}
}
step++;
q1=q2;
q2=temp;
}
return -1;
}
};
11.二进制矩阵中的最短路径
题目来源:1091. 二进制矩阵中的最短路径
题解:
class Solution {
public:
int dir[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,0},{1,-1},{1,1}};
int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
int n=grid.size();
int m=grid[0].size();
if(grid[0][0]!=0) return -1;
if(grid[n-1][m-1]==1) return -1;
if(n==1) return 1;
queue<pair<int,int>> q;
q.push({0,0});
grid[0][0]=1;
int ans=1;
while(!q.empty()){
int k=q.size();
for(int r=0;r<k;r++){
pair<int,int> p=q.front();
q.pop();
int x=p.first;
int y=p.second;
for(int i=0;i<8;i++){
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx==n-1&&yy==m-1){
return ans+1;
}
if(xx>=0&&yy>=0&&xx<n&&yy<m){
if(grid[xx][yy]==0){
q.push({xx,yy});
grid[xx][yy]=1;
}
}
}
}
ans+=1;
}
return -1;
}
};
12.二叉树中所有距离为 K 的结点
题目来源:863. 二叉树中所有距离为 K 的结点
题解:
/**
* 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 {
vector<int> g[510];
vector<int> ans;
public:
void BFS(TreeNode *root)
{
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
auto head=q.front();
q.pop();
if(head->left)
{
q.push(head->left);
g[head->val].push_back(head->left->val);
g[head->left->val].push_back(head->val);
}
if(head->right)
{
q.push(head->right);
g[head->val].push_back(head->right->val);
g[head->right->val].push_back(head->val);
}
}
}
void DFS(vector<bool>& vis,int root,int k,int step)
{
vis[root]=true;
if(step==k)
{
ans.push_back(root);
return;
}
for(int i=0;i<g[root].size();i++)
{
if(!vis[g[root][i]]) DFS(vis,g[root][i],k,step+1);
}
}
vector<int> distanceK(TreeNode* root, TreeNode* target, int k) {
vector<bool> vis(510,false);
BFS(root);
DFS(vis,target->val,k,0);
return ans;
}
};