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