lintcode亞馬遜

768.楊輝三角

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 &paragraph, 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;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章