编程之旅-Day40

Day40-学习内容:

目录

Day40-学习内容:

1.剑指Offer

面试题52:求两个链表的第一个公共结点

面试题27:二叉树的镜像

 2.Leetcode

例1:二叉搜索树的最近公共祖先

例2:二叉树的最近公共祖先

例3:爬楼梯

例4:编辑单词间的距离

3.华为机试题

例1:字符个数统计

例2:数字颠倒

例2:数字颠倒

 


1.剑指Offer

面试题52:求两个链表的第一个公共结点

题目描述:

输入两个链表,找出它们的第一个公共结点。

思路:长短指针

代码:

class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if(pHead1==nullptr||pHead2==nullptr){
            return nullptr;
        }
        ListNode* pNode1=pHead1;   //分别求长度
        ListNode* pNode2=pHead2;
        int len1=0;
        int len2=0;
        while(pNode1!=nullptr){
            len1++;
            pNode1=pNode1->next;
        }
        while(pNode2!=nullptr){
            len2++;
            pNode2=pNode2->next;
        }
        
        ListNode* pLong=pHead1;   //长链表先走几步
        ListNode* pShort=pHead2;
        int diff=len1-len2;
        if(len2>len1){
            pLong=pHead2;   //长链表先走几步
            pShort=pHead1;
            diff=len2-len1;
        }
        for(int i=0;i<diff;i++){
            pLong=pLong->next;
        }
        
        while(pLong&&pShort&&(pLong!=pShort)){  //得到公共节点
            pLong=pLong->next;
            pShort=pShort->next;
        }
        return pLong;
    }
};

面试题27:二叉树的镜像

题目描述:

操作给定的二叉树,将其变换为源二叉树的镜像。

输入描述:

二叉树的镜像定义:源二叉树 
    	    8
    	   /  \
    	  6   10
    	 / \  / \
    	5  7 9 11
    	镜像二叉树
    	    8
    	   /  \
    	  10   6
    	 / \  / \
    	11 9 7  5

思路:画图找规律,递归思想

代码:

class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        if(pRoot==nullptr){
            return;
        }
        if(pRoot->left==nullptr&&pRoot->right==nullptr){
            return;
        }
        TreeNode *pTemp=pRoot->left;
        pRoot->left=pRoot->right;
        pRoot->right=pTemp;
        if(pRoot->left){
            Mirror(pRoot->left);
        }
        if(pRoot->right){
            Mirror(pRoot->right);
        }
    }
};

 2.Leetcode

例1:二叉搜索树的最近公共祖先

题目描述:

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

说明:

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉搜索树中。

思路:递归,利用二叉搜索树的特点

代码:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==nullptr||p==nullptr||q==nullptr){
            return nullptr;
        }
        int big=p->val;
        int small=q->val;
        if(q->val>p->val){
            big=q->val;
            small=p->val;
        }
        if(root->val>=small&&root->val<=big){
            return root;
        }
        else if(root->val>small&&root->val>big){
            return lowestCommonAncestor(root->left,p,q);
        }
        else{
            return lowestCommonAncestor(root->right,p,q);
        }
    }
};

例2:二叉树的最近公共祖先

题目描述:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

思路:递归

代码:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (!root){
            return NULL;
        }
        if (root == p || root == q){
            return root;
        }
        TreeNode* left = lowestCommonAncestor(root -> left, p, q);
        TreeNode* right = lowestCommonAncestor(root -> right, p, q);
        if (left && right){ //  p, q 分别位于 x 的左子树和右子树;
            return root;
        }else if (left){ // p, q 都在 x 的左子树(也包括祖先其自身,另一个字节点在左子树);
            return left;
        }else if (right){ // p, q 都在 x 的右子树(也包括祖先其自身,另一个字节点在右子树);
            return right;
        }
        return NULL;
    }
};

例3:爬楼梯

题目描述:

You are climbing a stair case. It takes n steps to reach to the top. 

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

代码:

方法1:暴力法,超时不通过!

class Solution {
public:
    int climbStairs(int n) {
        if(n<1){
            return 0;
        }
        if(n==1){
            return 1;
        }
        if(n==2){
            return 2;
        }
        return climbStairs(n-1)+climbStairs(n-2);
    }
};

方法2:非递归,用for循环模拟

class Solution {
public:
    int climbStairs(int n) {
        int result = 1, pre = 0;
        for (int i = 1; i <= n; i++) {
            int tmp = result;
            result += pre;
            pre = tmp;
        }
        return result;
    }
};

方法3:动态规划

class Solution {
public:
    int climbStairs(int n) {
        int* dp = new int[n+1];
        dp[0]=1;
        dp[1]=1;
        for(int i=2;i<=n;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];
    }
};

 

例4:编辑单词间的距离

题目描述:

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.) 

You have the following 3 operations permitted on a word: 

a) Insert a character
b) Delete a character
c) Replace a character

思路:动态规划

代码:

class Solution {
public:
    int minDistance(string word1, string word2) {
        int m=word1.size();
        int n=word2.size();
        vector<vector<int>> dp(m+1,vector<int>(n+1));  // dp[i][j]代表由word1的前i个子串变为word2的前j个子串的花费
        // 其中i,j均可为0,代表空串:""
        
        for(int i=0;i<=m;i++){
            for(int j=0;j<=n;j++){    
                if(i==0){   // 首先初始化两个子串中有一个为空串的情况
                    dp[i][j]=j;
                } 
                else if(j==0){   // 首先初始化两个子串中有一个为空串的情况
                    dp[i][j]=i;
                }   
                else{  
// 如果这两个字符相等,那么交由上一种情况处理,如abc,dfc
                // 这种情况与ab,df花费是一样的
                // 不然就要在删除,插入,修改中取花费最小的那个
                    dp[i][j]=min(dp[i-1][j]+1,min(dp[i][j-1]+1,(dp[i-1][j-1]+(word1[i-1]==word2[j-1]?0:1))));
                }
            }
        }
        return dp[m][n];
    }
};

 

3.华为机试题

例1:字符个数统计

题目描述:

编写一个函数,计算字符串中含有的不同字符的个数。字符在ACSII码范围内(0~127)。不在范围内的不作统计。

输入描述:

输入N个字符,字符在ACSII码范围内。

输出描述:

输出范围在(0~127)字符的个数。

示例1

输入

abc

输出

3

思路:set用法

代码:

#include <iostream>
#include <set>

using namespace std;

int main(){
    char c;
    set<char> s;
    while(cin>>c){
        if(c>=0&&c<=127){
            s.insert(c);
        }
    }
    cout << s.size() << endl;
}

例2:数字颠倒

题目描述:

输入一个整数,将这个整数以字符串的形式逆序输出 

程序不考虑负数的情况,若数字含有0,则逆序形式也含有0,如输入为100,则输出为001 

输入描述:

输入一个int整数

输出描述:

将这个整数以字符串的形式逆序输出

示例1

输入

1516000

输出

0006151

思路:整数转换为字符串

代码:

#include <iostream>

using namespace std;

int main(){
    int n;
    while(cin>>n){
        string str;
        while(n){
            str+=(n%10)+'0';
            n=n/10;
        }
        cout << str << endl;
    }
    return 0;
}

例3:字符串翻转

题目描述:

写出一个程序,接受一个字符串,然后输出该字符串反转后的字符串。例如:

输入描述:

输入N个字符

输出描述:

输出该字符串反转后的字符串

示例1

输入

abcd

输出

dcba

代码:

#include <iostream>
#include <algorithm>

using namespace std;

int main(){
    string str;
    while(getline(cin,str)){
        reverse(str.begin(),str.end());
        cout << str << endl;
    }
    return 0;
}
#include <iostream>

using namespace std;

int main(){
    string str;
    while(getline(cin,str)){
        string str2;
        int len=str.length();
        
        for(int i=len-1;i>=0;i--){
            str2+=str[i];
        }
        
        cout << str2 << endl;
    }
    return 0;
}

 

猜你喜欢

转载自blog.csdn.net/linyuhan3232/article/details/89598188