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;
    }
};

 

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