广联达线下笔试题

1:给一个词典,找出其中所有最长的单词。
样例
在词典
{
“dog”,
“google”,
“facebook”,
“internationalization”,
“blabla”
}
中, 最长的单词集合为 [“internationalization”]
在词典
{
“like”,
“love”,
“hate”,
“yes”
}
中,最长的单词集合为 [“like”, “love”, “hate”]

思路:因为最长的单词集合可能为多个,所以使用数组作为返回值。
利用临时变量记录字典中单词的长度,如果比它长就添加到返回数组里面,并把长的替换为临时变量,如何长度一样就添加到返回数据里面,如果小于临时变量的长度,就跳出一次循环,最后返回一个数组,即为最长单词。

#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Soluton{
    vector<string> LongWords(vector<string>& dic)
    {
        vector<string> v;
        if (dic.empty())
        {
            return v;
        }
        string s;
        for (int i = 0; i < dic.size(); ++i)
        {
            if (dic[i].size() > s.size())
            {
                v.clear();
                v.push_back(dic[i]);
                s = dic[i];
            }
            else if (dic[i].size() == s.size())
            {
                v.push_back(dic[i]);
                s = dic[i];
            }
            else
            {
                continue;
            }
        }
        return v;
    }

};

2.求链表的倒数第k个节点,计数从1开始。
思路:为了实现只遍历链表一次就能找到倒数第 k 个结点,我们可以定义两 个指针。第一个指针从链表的头指针开始遍历向前走 k-1步,第二个指针保持不动;从第k 步开始,第二个指针也开始从链表的头指针开始遍历。由于两个指针的距离保持在 k-1 , 当第一个(走在前面的)指针到达链表的尾结点时,第二个指针(走在后面的)指针正好是倒数第 k 个结点。
code

#include <iostream>
using namespace std;
struct Node
{
    Node(int value = 0)
    :_value(value)
    , _next(NULL)
    {}
    int _value;
    Node* _next;
};

class Soluton
{
    Node* GetKthToTail(Node* head, int k)
    {
        if (k < 1 || head == NULL)
        {
            return NULL;
        }
        Node* fast = head;
        for (int i = 1; i < k; i++)
        {
            if (fast->_next != NULL)
                fast = fast->_next;
            else
                return NULL; //k的值大于链表节点个数
        }
        while (fast->_next != NULL)
        {
            head = head->_next;
            fast = fast->_next;
        }
        return head;
    }
};

3.创建一棵二叉树,并实现这棵二叉树的前序遍历。
思路:递归建树,前序递归/非递归遍历。
code

#include <iostream>
#include <stack>
#include <assert.h>
using namespace std;

struct Node
{
    Node(const int& value = 0)
    :_value(value)
    , _Lchild(NULL)
    , _Rchild(NULL)
    {}
    int _value;
    Node* _Lchild;
    Node* _Rchild;
};

class BinaryTree{
private:
    Node* _root;
public:
    BinaryTree()//无参构造函数
        :_root(NULL)
    {}
    BinaryTree(const int* a, int size, const char& invalid)//构造函数
    {
        assert(a);
        int index = 0;
        _root = CreateTree(a, size, invalid, index);
    }
    ~Binary()
    {
        if (NULL != _root)
        {
            Destroy(_root);
            _root = NULL;
        }
    }

    //前序递归遍历
    void PreOrder(Node* root)
    {
        if (NULL == root)
            return;
        cout << root->_value << " ";
        PreOrder(root->_Lchild);
        PreOrder(root->_Rchild);
    }

    //前序非递归
    void PreOrderNoR(Node* root)
    {
        Node* cur = root;
        stack<Node*> s;
        while (!s.empty() || cur)
        {
            while (cur)
            {
                cout << cur->_value << " ";
                s.push(cur);
                cur = cur->_Lchild;
            }
            Node* top = s.top();
            s.pop();
            cur = cur->_Rchild;
        }
        cout << endl;
    }
protected:
    Node* CreateTree(const int* a, int size, const char& invalid,int& index)
    {
        assert(a);
        Node* root = NULL;
        if (a[index] != invalid && index < size)
        {
            root = new Node(a[index]);
            root->_Lchild = CreateTree(a, size, invalid, index++);
            root->_Rchild = CreateTree(a, size, invalid, index++);
        }
        return root;
    }

    void Destroy(Node* root)//递归释放
    {
        if (NULL != _root)
        {
            Destroy(root->_Rchild);
            Destroy(root->_Lchild);
            delete root;
            root = NULL;
        }
    }
};

4.求二叉树的镜像。
思路:判断节点是否为空,不为空直接交换左右孩子即可。
code:

void Mirror(Node* root)
{
    if (root == NULL)
        return;
    swap(root->_Lchild, root->_Rchild);
    Mirror(root->_Lchild);
    Mirror(root->_Rchild);
}

5.有n座别墅,每座别墅有不同的财产,小偷每次只能偷一家,偷完一家之后,这家相邻的两家不可以再偷了,求小偷最多能偷到的财产。
思路:(典型动态规划问题)

1 假设小偷偷得顺序是按照从左往右,那么最终停止的位置只能是9或10
2 如果从位置10往前回溯,分别有两个可以选择的房子7和8,位置9也是一样的
3 需要选择从左边开始到money数目最大的那个房子,那么可以看到这是一个递归的过程
4 因为中间会有一些重复的计算,比如在求位置10的向前回溯的时候,需要计算位置7的money值,计算位置9前溯同样需要计算位置7的money,所以我们需要将已经计算过的值进行记录

code

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

class Solution
{
public:
    int GetMaxMoney(vector<int>& nums)
    {
        int len = nums.size();
        MaxMoney.resize(len, -1);
        int m1 = GetMoney(nums, len - 1);
        int m2 = GetMoney(nums, len - 2);
        return m1 > m2 ? m1 : m2;
    }
    int GetMoney(vector<int>& nums, int pos)
    {
        if (pos < 0)
            return 0;
        if (MaxMoney[pos] >= 0)//判断是否已经计算过当前的位置
            return MaxMoney[pos];
        int max1 = GetMoney(nums, pos - 2);
        int max2 = GetMoney(nums, pos - 3);
        MaxMoney[pos] = (max1 > max2 ? max1 : max2) + nums[pos];
        return MaxMoney[pos];
    }

private:
    vector<int> MaxMoney;
};

int main()
{
    int arr[] = { 2, 3, 4, 1, 9, 3, 2, 3, 3, 4 };
    Solution so;
    vector<int> int_vec(arr, arr + sizeof(arr) / sizeof(int));
    cout << so.GetMaxMoney(int_vec);
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值