[学习笔记-C++篇]day13-14 lintcode50

50+100+针对训练。
感谢大佬几款优秀的支持C、C++在线编译器

此外,教程网站:九章算法课-免费试听可以闲的时候过渡一下,换换思路听着。

另,十大排序算法需要整理一下,参考:1.0 十大经典排序算法
其实主要要整理数据结构与算法


stage2——4天进阶阶段

在线编译器:compile c++ gcc online
刷题网站:阶段1第一关:基本数据类型

day2-3 planA
lintcode 余4-6
教程完成度100%。


1.两字符串和

接着昨天的继续。

字符转数字:char c; int i=c-'0';,注意,减去的是字符'0',不是数字。
数字转字符:int i; char c=i+'0';,注意,加上的还是字符'0',不是数字。

此外,数字转字符其实用的是to_string,因为可能出现加和为两位数的情况。

class Solution {
public:
    /**
     * @param A: a string
     * @param B: a string
     * @return: return the sum of two strings
     */
    string SumofTwoStrings(string &A, string &B) {
        // write your code here

#if 1 //第1种
        
        int size=A.size()>B.size()?A.size():B.size();
        int sum;//每一位和
        string S;//保存结果

        int a=stoi(A),b=stoi(B);

        for(int i=0;i<size;i++)
        {
            sum=a%10+b%10;
            S=to_string(sum)+S;
            a/=10;
            b/=10;
        }

        return S;
#endif
    }
};

昨天说到stoi函数有检测范围的问题。
当字符串中有除了数字外的字符时,只会将这些字符前的数字转换为int
此外还有atoi函数,stoi的参数是const string*atoi的参数是const char*

因此改进下:

class Solution {
public:
    /**
     * @param A: a string
     * @param B: a string
     * @return: return the sum of two strings
     */
    string SumofTwoStrings(string &A, string &B) {
        // write your code here

        //原思路,取每位转数字求和再转字符
        int size=A.size()<B.size()?A.size():B.size();
        int sum;
        string S="";
        string rest;

        for(int i=0;i<size;i++)
        {
            sum=(A[A.size()-1-i]-'0')+(B[B.size()-1-i]-'0');
            S=to_string(sum)+S;
        }

        if(A.size()>size) rest.assign(A,0,A.size()-size);
        else if(B.size()>size) rest.assign(B,0,B.size()-size);
        S=rest+S;

        return S;
    }
};

今天再强调另一个要点:
s.assign(str,index);默认只有字符串和数字两个参数的时候,是将strindex起的所有元素赋值给s,而不是将前index个字符进行赋值。如果要给定区间,使用s.assign(str,index,num)

2.首字母大写

类似【翻转字符串问题】,参见[学习笔记-C++篇]day11 lintcode50

class Solution {
public:
    /**
     * @param s: a string
     * @return: a string after capitalizes the first letter
     */
    string capitalizesFirst(string &s) {
        // Write your code here

        string str;
        bool judge=true;
        for(int i=0;i<s.size();i++)
        {
            if(s[i]!=' ' && judge==true)
            {
                if(islower(s[i])) str.push_back(s[i]-32);
                judge=false;
                continue;
            }
            else if(s[i]==' ')     judge=true; 
            str.push_back(s[i]);
        }
        return str;
    }
};

3.回文数

类似【回文数2】,参见[学习笔记-C++篇]day11 lintcode50

但是当时只熟悉到vector,所以遍历取数字每一位保存到数组中,然后翻转数组。

现在可以直接用intstring,实现翻转。

class Solution {
public:
    /**
     * @param num: a positive number
     * @return: true if it's a palindrome or false
     */
    bool isPalindrome(int num) {
        // write your code here
        string s,rs;
        s=to_string(num);
        rs=s;
        reverse(rs.begin(),rs.end());
        if(s==rs) return true;
        else return false;
    }
};

4.最长单词

暴力环。

class Solution {
public:
    /*
     * @param dictionary: an array of strings
     * @return: an arraylist of strings
     */
    vector<string> longestWords(vector<string> &dictionary) {
        // write your code here

        //遍历1次,那么一旦出现大于现有值的时候就需要清空数组
        vector<string> sout;
        sout.push_back(dictionary[0]);

        int tmp;//保存字符串临时长度
        tmp=dictionary[0].size();        

        for(int i=1;i<dictionary.size();i++)
        {
            if(dictionary[i].size()==tmp) sout.push_back(dictionary[i]);
            else if(dictionary[i].size()>tmp)
            {
                sout.clear();
                sout.push_back(dictionary[i]);
                tmp=dictionary[i].size();
            }
        }

        return sout;
    }
};

会超时。不管了,别的题解也有这样的思路,但是不会超时?离谱。

class Solution {
public:
    /*
     * @param dictionary: an array of strings
     * @return: an arraylist of strings
     */
    vector<string> longestWords(vector<string> &dictionary) {
        // write your code here
        
        int tmp=0;
        for(int i=0;i<dictionary.size();i++)
        {
            tmp=tmp>=dictionary[i].size()?tmp:dictionary[i].size();
        }

        vector<string> sout;
        for(int j=0;j<dictionary.size();j++)
        {
            if(dictionary[j].size()==tmp) sout.push_back(dictionary[j]);
        }

        return sout;
    }
};

还是会卡,反正暴力就是会卡时间。

5.最后一个单词的长度

仍旧和第2题类似。

注意点:1)字符串是否为空;2)最后一个单词是否含有空格。

就如何删除string中空格的指令,我给出了2个答案,但是奇怪的是,用#if 0注释掉的部分在编译器中是可以正确运行的,但是核心代码无法正确识别。

参考C++从string中删除所有的某个特定字符
法1:str.erase(index,num);删除字符串str中从索引index开始的num个元素。
法2:str.erase(remove(str.begin(),str.end(),c),str.end());先用remove删除字符串str中等于字符c的元素,得到一个新的字符串,但remove的返回值是一个迭代器(指向新容器的end),然后结合erase删除从迭代器开始到end的元素,就是新的str

class Solution {
public:
    /**
     * @param s: A string
     * @return: the length of last word
     */
    int lengthOfLastWord(string &s) {
        // write your code here

        bool judge=true;//协同判断
        int start;//保存最后一个单词的起始索引

        string stmp;//用于剔除单词中多余的空格

        if(s.empty()) return 0;
        else
        {
            for(int i=0;i<s.size();i++)
            {
                if(s[i]!=' ' && judge)    { start=i; judge=false; }
                else if(s[i]==' ') judge=true;
            }
            stmp.assign(s,start);
            
            #if 0
            for(int j;j<stmp.size();j++)
            {
                if(stmp[j]==' ') stmp.erase(j,1);
            }
            #endif

            stmp.erase(remove(stmp.begin(),stmp.end(),' '),stmp.end());
            return stmp.size();

        } 
    }
};

6.最大字母

其实代码很简单,但是难点在于理解题目。

翻译一下题目:给一个字符串,返回一个字符串。判断返回值条件:若输入中存在同一字母的大小写,且该大写字母的ascii码最大,则返回该大写字母字符串;否则返回"NO"

class Solution {
public:
    /**
     * @param s: a string
     * @return: a string
     */
    string largestLetter(string &s) {
        // write your code here

        //先找出大写字母最大,然后判断是否对应小写
        char up='A';
        bool ju,jl;
        ju=false;jl=false;
        string re;//返回值

        for(int i=0;i<s.size();i++)
        {
            if(s[i]>='a' && s[i]<='z') continue;
            else { up=up>s[i]?up:s[i]; ju=true;}
        }

        if(ju)
        { 
            for(int j=0;j<s.size();j++)
            {
                if(up+32==s[j]) { re.push_back(up); return re; }
                else jl=false;
            }
            if(!jl) return "NO";
        }   
        else return "NO";    
    }
};

7.旋转字符串

类似[学习笔记-C++篇]day11 lintcode50中的翻转字符串。

class Solution {
public:
    /**
     * @param s: An array of char
     * @param offset: An integer
     * @return: nothing
     */
    void rotateString(vector<char> &s, int offset) {

        int k=offset%s.size();
        string stmp;

        for(int i=0;i<s.size();i++)
        {
            stmp.push_back(s[i]);
        }

        if(s.size()==0 || k==0) return;
        else
        {
            stmp=stmp.substr(s.size()-k)+stmp.substr(0,s.size()-k);
            s.assign(stmp.begin(),stmp.end());
        }
    }
};

思路应该是没问题的,但测试用例"",会报错。

8.二阶阶乘

用到向上取整函数ceiln=ceil(num);,注意为了保证num为小数要用double类型。

class Solution {
public:
    /**
     * @param n: the given number
     * @return:  the double factorial of the number
     */
    long long doubleFactorial(int n) {
        // Write your code here

        long long op=1;
        int tmp=n;
        for(int i=0;i<n/2;i++)
        {
            op*=tmp;
            tmp-=2;
        }
        return op;
    }
};

9.实现栈

需要整理栈类的用法。应该会整理在STL教程中。

在这边我采用了vector,比较熟悉。但是空间消耗很大。

class Stack {
public:
    /*
     * @param x: An integer
     * @return: nothing
     */
    vector<int> test;

    void push(int x) {
        // write your code here
        test.push_back(x);
    }

    /*
     * @return: nothing
     */
    void pop() {
        // write your code here
        test.pop_back();
    }

    /*
     * @return: An integer
     */
    int top() {
        // write your code here
        return test[test.size()-1];
    }

    /*
     * @return: True if the stack is empty
     */
    bool isEmpty() {
        // write your code here
        if(test.size()==0) return true;
        else return false;
    }
};

10.队列维护

class MyQueue {
public:
    /*
     * @param item: An integer
     * @return: nothing
     */

    deque<int> l;
    void enqueue(int item) {
        // write your code here
        l.push_back(item);
    }

    /*
     * @return: An integer
     */
    int dequeue() {
        // write your code here
        int tmp=l.front();
        l.pop_front();
        return tmp;
    }
};

11.有效的括号序列

首先不论对错,先说下思路。

string转到stack中,然后对每一位字符判断,如果是三种左括号之一,判断下一位是不是对应右括号,是就pop()2次,索引后移2位;不是,索引后移1位;不是左括号也右移1位索引。最后判断stacksize()

class Solution {
public:
    /**
     * @param s: A string
     * @return: whether the string is a valid parentheses
     */
    bool isValidParentheses(string &s) {
        // write your code here
        stack<char> ss;
        for(auto c:s) ss.push(c);

        for(int i=0;i<s.size();)
        {
            switch(s[i])
            {
                case '(' : {if(s[i+1]==')') {ss.pop();ss.pop();i+=2;break;} i++;break;}
                case '[' : {if(s[i+1]==']') {ss.pop();ss.pop();i+=2;break;} i++;break;}
                case '{' : {if(s[i+1]=='}') {ss.pop();ss.pop();i+=2;break;} i++;break;}
                default: i++;break;
            }
        }

        if(ss.size()==0) return true;
        else return false;
    }
};

但是,题目不是说必须得()[]{}吗,怎么([])也对??

所以还需要考虑交叉出现的矛盾。就需要重新生成右括号,然后判断消去的时候会不会有间隔其他符号。

class Solution {
public:
    /**
     * @param s: A string
     * @return: whether the string is a valid parentheses
     */
    bool isValidParentheses(string &s) {
        // write your code here
        stack<char> ss;
        for(auto c:s)
        {
            switch(c)
            {
                case '(': ss.push(')');break;
                case '[': ss.push(']');break;
                case '{': ss.push('}');break;
                default:
                    if(ss.empty() || ss.top()!=c)
                    return false;
                    ss.pop();
                    break;
            }
        }

        return ss.size()==0;
        
    }
};

12.小括号匹配

和上一题一样。

不要为了偷懒用什么string s(string);这种啊,输入参数和类型名重复了,会报错。

class Solution {
public:
    /**
     * @param string: A string
     * @return: whether the string is valid 
     */
    bool matchParentheses(string &string) {
        // write your code here

        stack<char> ss;
        for(auto c:string)
        {
            switch(c)
            {
                case '(': ss.push(')'); break;
                case '[': ss.push(']'); break;
                case '{': ss.push('}'); break;
                default:
                    if(ss.empty() || c!=ss.top())
                    return false;
                    ss.pop();
                    break;
            }
        }

        return ss.size()==0;
    }
};

13.斐波那契数列

class Solution {
public:
    /**
     * @param n: an integer
     * @return: an ineger f(n)
     */
    int fibonacci(int n) {
        // write your code here

        int l,r,t;

        if(n==1) return 0;
        if(n==2) return 1;

        for(int i=0;i<n;i++)
        {
            if(i==0) { l=0; continue;}
            if(i==1) { r=1; continue;}
            t=l+r;

            l=r;
            r=t;
        }
        return t;
    }
};

用递归:

class Solution {
public:
    int fibonacci(int n) {
        if (n <= 2) {
            return n - 1;
        }
        
        int fib[2];
        fib[0] = 0;
        fib[1] = 1;
        for (int i = 2; i < n; i++) {
            fib[i % 2] = fib[0] + fib[1];
        }
        
        return fib[(n+1)%2];
    }
};

构建递归函数:
参考:解题思路
这里的思路是从最后一个往前递推到最初的2个数。然后一步步加起来。

class Solution {
public:
    int dfs(int n, int fib[]) {
        if (fib[n] != -1) {
            return fib[n];
        }
        if (n <= 2) {
            fib[n] = n - 1;
            return fib[n];
        }
        fib[n] = dfs(n - 1, fib) + dfs(n - 2, fib);
        
        return fib[n];
    } 
     
    int fibonacci(int n) {
        int result[n + 1];
        for (int i = 0; i <= n; i++) {
            result[i] = -1;
        }
        dfs(n, result);
        
        return result[n];
    }
};

14.二叉树的遍历

前序:根左右
中序:左根右
后序:左右根

参考数据结构与算法——普通树的定义与C++实现

先临时整理一下。
TreeNode类型

TreeNode *root;
root->left 取左子
root->right 取右子
root->val 取root中的值
root!=nullptr 判断指针是否为空

  class TreeNode {
  public:
      int val;
      TreeNode *left, *right;
      TreeNode(int val) {
          this->val = val;
          this->left = this->right = NULL;
      }
  }


注意:
1)使用root指针,结合->
2)调用递归函数,要记得给数组加上引用符&
3)判断指针是否为空的时候,要把!符号和判空指令root->nullptr分开

14.1 前序遍历

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: A Tree
     * @return: Preorder in ArrayList which contains node values.
     */

    void dps(TreeNode *r,vector<int> &p)
	{
        p.push_back(r->val);
		if(!(r->left==nullptr)) dps(r->left,p);
		if(!(r->right==nullptr)) dps(r->right,p);
	}
    
    vector<int> inorderTraversal(TreeNode *root) {
        // write your code here
	   vector<int> post;
	   if(!(root==nullptr)) dps(root,post);

	   return post;
    }
};

后台又抽了。

14.2 中序遍历

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: A Tree
     * @return: Inorder in ArrayList which contains node values.
     */
	
	void dps(TreeNode *r,vector<int> &p)
	{
		if(!(r->left==nullptr)) dps(r->left,p);
		p.push_back(r->val);
		if(!(r->right==nullptr)) dps(r->right,p);
	}
    vector<int> inorderTraversal(TreeNode *root) {
        // write your code here
	   vector<int> post;
	   if(!(root==nullptr)) dps(root,post);

	   return post;
    }
};

14.3 后序遍历

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: A Tree
     * @return: Postorder in ArrayList which contains node values.
     */
	void dps(TreeNode *r,vector<int> &p)
	{
		if(!(r->left==nullptr)) dps(r->left,p); 
		if(!(r->right==nullptr)) dps(r->right,p);
		p.push_back(r->val);
	}

    vector<int> postorderTraversal(TreeNode *root) {
        // write your code here

	   vector<int> post;
	   if(!(root==nullptr)) dps(root,post);

	   return post;
    }
};

15.阶段性完结

在这里插入图片描述
纪念一下,虽然47/50=78%,虽然没完成3道是因为超时无法运行或后台问题,虽然菜,但是要纪念一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值