class Solution {
public:
vector<vector<int>> calcYangHuisTriangle(int n) {
vector<vector<int>> res;
vector<int> last;
last.push_back(1);
if (n==0) return res;
res.push_back(last);
if (n==1) return res;
for (int i=1;i<n;i++) {
vector<int> now;
for (int j=0;j<=last.size(); j++) {
if (j==0 ||j==last.size()) { now.push_back(1); continue; }
now.push_back(last[j]+last[j-1]);
}
res.push_back(now);
last=now;
}
return res;
}
};
1354. 楊輝三角形II
空間複雜度O(k),只用一個數組反覆迭代,前後加0即可。
class Solution {
public:
vector<int> getRow(int rowIndex) {
// write your code here
vector<int> last={0,1,0};
if (rowIndex==0) return vector<int>(last.begin()+1,last.end()-1);
for (int i=0;i<rowIndex;i++) {
for (int j=0;j<last.size()-1; j++) {
last[j]=last[j]+last[j+1];
}
//後面的0仍保留,前面的0再加上
last.insert(last.begin(),0);
}
return vector<int>(last.begin()+1,last.end()-1);
}
};
1369. 最頻繁單詞
細節很多,transform(paragraph.begin(),paragraph.end(),paragraph.begin(),::tolower) 轉成小寫,注意字符串尾沒有空格也要記錄單詞。
class Solution {
public:
string mostCommonWord(string ¶graph, vector<string> &banned) {
if (paragraph.size()==0) return "";
transform(paragraph.begin(),paragraph.end(),paragraph.begin(),::tolower);
unordered_set<string> banned_word;
unordered_map<string,int> word_freq;
for (int i=0;i<banned.size();i++) banned_word.insert(banned[i]);
int i=0;
string word="";
int max_freq=0;
string res="";
while (i<=paragraph.size()) {
if (paragraph[i]>='a' && paragraph[i]<='z') {
word=word+paragraph[i];
}
else if (paragraph[i]==' ' ||i==paragraph.size()){
if (banned_word.count(word)==0){
if (word_freq.count(word)>0) word_freq[word]++;
else word_freq[word]=1;
if (word_freq[word]>max_freq) {
max_freq=word_freq[word];
res=word;
}
}
word="";
}
i++;
}
return res;
}
};
1227. 重複的子串模式
一開始的思路是,模式串最少是由兩個重複串組成的,最少是有1個字符組成,所以暴力搜索所有可能子串,以第一個假定子串爲標準,後面的如果和它都一樣說明是重複的字串模式。
class Solution {
public:
bool repeatedSubstringPattern(string &s) {
// write your code here
if (s=="") return false;
int n=s.length();
for (int i=n/2;i>=1;i--) {
if (n%i!=0) continue;
string base=s.substr(0,i);
int j;
for (j=i;j<n;j++)
if (s[j]!=base[j%i]) break;
if (j==n) return true;
}
return false;
}
};
比較牛逼的方法:對於一個模式串組成的字符串s,其模式串的長度最長爲s的一半,即在s是由模式串組成的前提下時,s中至少包含兩部分相同的模式串,那麼s + s則至少包含四部分的模式串,如果去掉s + s中的第一個和最後一個字符,此時仍存在兩個相鄰的模式串,如果在r = (s + s)[1...-1]中能夠找到s,說明原始的s是由模式串組成的。
注意字符串中搜索子串的方法:source.find(target)!=string::npos
class Solution {
public:
bool repeatedSubstringPattern(string s) {
string r = s.substr(1) + s.substr(0, s.size() - 1);
return r.find(s) != string::npos;
}
};
1746. 二叉搜索樹結點最小距離
一開始想麻煩了,覺得最小距離只能在相鄰兩層出現,寫了個層序遍歷。但是類似[4,1,#,#,3]就不對。所以只能遍歷整棵樹,把值記錄下來,然後在相鄰兩數間找最小值。也可以記錄前一個遍歷的值,儘量少佔用內存空間。但是要注意跟着函數遞歸的話要寫成指針,否則這個值記錄在棧裏會不停的變。
class Solution {
private:
int res;
public:
void help (TreeNode * root,int* last_val) {//接收的也是指針
if (root==NULL) return;
help(root->left,last_val);
if (*last_val!=-1) res=min(res,abs((*last_val)-root->val));//*是取指針指向的值
*last_val=root->val;//改裏面的值加*
help(root->right,last_val);
}
int minDiffInBST(TreeNode * root) {
// Write your code here.
if (root==NULL) return 0;
res=INT_MAX;
int* last=new int(-1);//新建一個叫last的指針指向一片內存
help(root,last);//傳指針
return res;
}
};
或者用&,這裏也有說明https://blog.csdn.net/musechipin/article/details/62221330
class Solution {
private:
int res;
public:
void help (TreeNode * root,int &last_val) {//新建一個傳過來的last的引用(不要理解成取地址),last和last_val都指向同一片內存
if (root==NULL) return;
help(root->left,last_val);//再調用的時候,新函數會新建一個last_val的引用,可能有很多引用,但是指向的內存都是一樣的,保證了這個數不隨遞歸改變
if (last_val!=-1) res=min(res,abs((last_val)-root->val));
last_val=root->val;
help(root->right,last_val);
}
int minDiffInBST(TreeNode * root) {
// Write your code here.
if (root==NULL) return 0;
res=INT_MAX;
int last=-1;
help(root,last);//傳一個數
return res;
}
};
1187. 數組中的K-diff對
這個題有個坑是,別的數字都可以使用多次只要有就可以,但k=0的時候必須有至少兩個相同的數纔行(自己和自己不行)
class Solution {
public:
int findPairs(vector<int> &nums, int k) {
// Write your code here
if (nums.size()<=0) return 0;
unordered_map<int,int> record;
for (int i=0;i<nums.size();i++) {
if (record.count(nums[i])!=0) record[nums[i]]++;
else record[nums[i]]=1;
}
int res=0;
for (auto number:record)
if (record.count(number.first+k)>0) {
if (k!=0) res++;
if (k==0 && record[number.first]>1) res++;
}
return res;
}
};
或者使用雙指針的方法,j從i後一位開始(保證不會出現1個數用兩次),i每次向後移動一個數,j可以連續向後移動(不用走回頭路,因爲排序之後i向後移則差變小,j不可能向前移)
class Solution{
public:
int findPairs(vector<int> &nums, int k)
{
int n = nums.size();
sort(nums.begin(), nums.end());
int ans = 0;
for (int i = 0, j = 0; i < n; i++)
{
if (i == j)
j++;
while (i + 1 < n && nums[i] == nums[i + 1])
i++;
while (j + 1 < n && nums[j] == nums[j + 1])
j++;
while (j < n && abs(nums[j] - nums[i]) < k)
j++;
if (abs(nums[j] - nums[i]) == k)
{
ans++;
j++;
}
}
return ans;
}
};
1137. 從二叉樹構建字符串
這個題一個是注意string和int的互轉,用stringstream,還有一個是注意它說的,缺省的才能省略,就是葉子結點的左右子樹可以省略,左子樹可以省略,但是右子樹是空必須加()。
class Solution {
public:
void help(TreeNode * t, string& s) {
if (t==NULL) return;
stringstream ss;
string tmp;
ss<<t->val;
ss>>tmp;
s=s+tmp;
if (t->left==NULL && t->right==NULL) return;
s=s+'(';
help(t->left,s);
s=s+')';
if (t->right!=NULL){
s=s+'(';
help(t->right,s);
s=s+')';
}
}
string tree2str(TreeNode * t) {
// write your code here
if (t==NULL) return NULL;
string s="";
help(t,s);
return s;
}
};
判斷給定單詞列表能否首位鏈接
討論:https://bbs.csdn.net/topics/70505395
1.需要構建有向圖,有兩種方法,一種是詞作爲點,一種是詞首和詞尾分別是兩個點,有詞則相連(這種明顯時間複雜度會低很多);
2.寬度優先搜索只能判斷圖是不是全連通(弱聯通),要想判斷能否一條路徑走完需要補充驗證歐拉回路(歐拉路徑)的條件
3.或者使用深度優先搜索,但是會會報錯,推測是時間複雜度太高
以下代碼是寬搜代碼,測試case全過了,但實際需要補全歐拉路徑驗證條件,即每個點出入度相等,允許有一個點入度少1,一個點入度多1。
#include <unordered_map>
#include <set>
#include <queue>
using namespace std;
int try_con(string head, unordered_map<string,set<string>> relation) {
set<string> v;
v.insert(head);
queue<string> h;
h.push(head);
while (!h.empty()) {
int l=h.size();
for (int i=0;i<l;i++) {
string f=h.front();
h.pop();
for (auto w:relation[f])
if (v.find(w)==v.end()) {
v.insert(w);
h.push(w);
}
}
}
return v.size();
}
int canArrangeWords(int num,char** arr){
// WRITE YOUR CODE HERE
if (num<=1) return 1;
unordered_map<string,set<string>> relation;
for (int i=0;i<num;i++) {
string tmp1=arr[i];
set<string> tmp;
for (int j=0;j<num;j++) {
if (i==j) continue;
string tmp2=arr[j];
if (tmp1[tmp1.length()-1]==tmp2[0])
tmp.insert(tmp2);
}
relation[tmp1]=tmp;
}
for (int i=0;i<num;i++) {
string head=arr[i];
if (try_con(head,relation)==num) return 1;
}
return -1;
}
1333. 顛倒二進制位
兩種算法,一種是短除法:
class Solution {
public:
/**
* @param n: an integer
* @return: return an integer
*/
long long reverseBits(long long n) {
// write your code here
long long res=0;
long long base=pow(2,31);
while (n>0) {
res=res + (n%2==1?base:0);
n=n/2;
base=base/2;
}
return res;
}
};
一種位運算:
class Solution {
public:
/**
* @param n: an integer
* @return: return an integer
*/
long long reverseBits(long long n) {
// write your code here
long long m=0;
for (int i=0;i<32;i++) {
m=m<<1;//先移一位的原因是第一位是符號位
m=m | (n &1);
n=n>>1;
}
return m;
}
};