欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

leetcode中剑指offer的习题 C++语言实现(1)

程序员文章站 2022-07-15 19:41:18
...

面试题5 替换空格

leetcode中剑指offer的习题 C++语言实现(1)
第一种方法使用str的成员函数replace来完成。
第二种方法先创建一个容量足够大的string,然后将源字符串中的元素一个一个加进去,如果遇到空格,则加入%20.

因为返回值是string需要调用构造函数,但是返回值后,局部变量将被销毁,所以调用std::move()将返回值转化为右值,使其调用移动构造函数,可以提高运行速度。

// #include<algorithm>
class Solution {
public:
    // string replaceSpace(string s) {
    //     size_t index = 0;
	// while (true) {
	// 	index = s.find(" ", index);
	// 	if (index!=-1)
	// 	{
	// 		s.replace(s.begin() + index, s.begin() + index + 1, "%20");
	// 	}
	// 	else {
	// 		break;
	// 	}
	// }
    // return s;
    // }
    string replaceSpace(string s) {
size_t count = 0;
	for (size_t i=0;i<s.size();++i)
	{
		if (s[i]==' ')
		{
			++count;
		}
	}
	
	string new_s(s.size()+count*2,' ');
	size_t index = 0;
	for (size_t i = 0; i < s.size(); ++i)
	{
		if (s[i]==' ')
		{
			new_s[index++] = '%';
			new_s[index++] = '2';
			new_s[index++] = '0';
		}
		else {
			new_s[index++] = s[i];
		}
	}
	// cout << new_s << endl;
    //使用move调用移动构造函数
    return std::move(new_s);
    }
};

leetcode中剑指offer的习题 C++语言实现(1)

面试题6 从头到尾打印链表

leetcode中剑指offer的习题 C++语言实现(1)
方法1,使用一个vector保存每一个链表的指针,遍历完链表之后反向输出即可。
方法2,使用递归,将值保存在vector容器中(书中的方法和这种类似)
方法3,因为只强调了逆序输出,所以可以顺序保存,只要将容器中的内容逆向输出即可

第三种方法需要仔细想一下,因为看到逆序输出我们的直觉往往是先从链表本身开始考虑,但是这道题可以从保存的序列上考虑。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        // vector<int> vec;
        //method 1 使用一个容器保存顺序
        if(head==nullptr){
            vector<int> vec;
            return std::move(vec);
        }
        // vector<ListNode*> arr;
        // // arr.reserve(10000);
        // ListNode* temp=head;
        // while(temp){
        //     arr.push_back(temp);
        //     temp = temp->next;
        // }
        // vector<int> vec(arr.size());
        // size_t index = 0;
        // std::for_each(arr.rbegin(),arr.rend(),[&vec,&index](const ListNode* temp){
        //     vec[index++] = temp->val;
        // });
        // return std::move(vec);
        //method2 使用递归  但是有栈溢出的风险
        // vector<int>vec;
        // get_value(vec,head);
        // return std::move(vec);
        //method3 直接打印,但是逆序输出
        vector<int> vec;
        ListNode* temp=head;
        while(temp){
            vec.push_back(temp->val);
            temp=temp->next;
        }
        std::reverse(vec.begin(),vec.end());
        return vec;
    }
    // void get_value(vector<int>& vec,ListNode* p){
    //     if(p==nullptr){
    //         return;
    //     }else{
    //         get_value(vec,p->next);
    //         // std::cout<<p->val<<std::endl;
    //         vec.push_back(p->val);
    //     }
    // }
};

第三种方法的执行时间最短
leetcode中剑指offer的习题 C++语言实现(1)

面试题7 重建二叉树

和书上的思路差不多,我自己写的还可以优化

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
 /*
 思路:
 使用递归的思想

 首先确定第一个根节点,然后再中序遍历中找到这个根结点的位置,以确定左右子树的范围

 有了左右子树的范围,就在子树中寻找根节点,然后在中序遍历中找到这个根节点的位置,再确定左右子树范围

 目前的缺点:其实不用确定范围,只需要确定左右子树的节点数量就可以了。

 如果节点数量为0,那么表示该子树为nullptr。
如果不为零,则继续往下遍历

 */
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size()==0){
            return nullptr;
        }

        //method1  使用递归的方法
        int cur_index = 0;
        //获取根节点
        TreeNode * p = new TreeNode(preorder[cur_index]);
        //找到根节点在中序遍历中的位置
        size_t inorder_index=  std::find(inorder.begin(), inorder.end(), preorder[cur_index]) - inorder.begin();
        cout<<inorder_index<<endl;
        //确定左右子树在中序遍历中的范围
        int left_begin=0;
        int left_end = inorder_index-1;
        int right_begin = inorder_index+1;
        int right_end = inorder.size()-1;
        //构建左子树
        build(p->left,preorder,inorder,cur_index,left_begin,left_end);
        //构建 右子树
        build(p->right,preorder,inorder,cur_index,right_begin,right_end);
        
        return p;
    }

    void build(TreeNode* &p,vector<int>& preorder, vector<int>& inorder,int &cur_index,int begin,int end){
        //判断当前节点是否应该为空
        // cout<<"cur_index"<<begin<<":"end<<endl;
        // return;
        if(begin>end){
            p=nullptr;
            return;
        }
        ++cur_index;
        //得到当前节点的值
        p = new TreeNode(preorder[cur_index]);
        //找到根节点在中序遍历中的位置
        size_t inorder_index=  std::find(inorder.begin(), inorder.end(), preorder[cur_index]) - inorder.begin();

        //确定左右子树在中序遍历中的范围
        int left_begin=begin;
        int left_end = inorder_index-1;
        int right_begin = inorder_index+1;
        int right_end =end;
         //构建左子树
        build(p->left,preorder,inorder,cur_index,left_begin,left_end);
        //构建 右子树
        build(p->right,preorder,inorder,cur_index,right_begin,right_end);
    }
};

leetcode中剑指offer的习题 C++语言实现(1)