暑期算法题练习
-
山羊拉丁文
[外链图片转存失败(img-mjMxzz4b-1568452381816)(/Users/magicmessi/Desktop/屏幕快照 2019-09-13 下午11.12.47.png)]
基本想法:根据空格将一句话拆开成多个单词,再对每个单词的开头进行分析,对每个单词进行修改,最后再用一个字符串将其连接起来进行输出。
c++代码:
class Solution{
public:
string toGoatLatin(string S){
string yy_alphabet = {"aAeEiIoOuU"};//元音字母表
string temp = " ";//临时存放需要转化的单词
string output = " ";//输出
string A = "a";//便于统计a的个数
for(int i=0; i<=S.length();i++){
if(S[i]!=' '&& i!=S.length()){
temp += S[i];
}//根据空格将句子拆开
else{
if(yy_alphabet.find(temp[0])!=yy_alphabet.npos)//判断是否为元音字母
{
output += temp + "ma" +A;
}
else{
temp += temp[0];
temp = temp.erase(0,1);//将第一个字母删除
output += temp + "ma" +A;
}
if(i!=S.length())
output += " ";//加上空格
A += "a";
temp = " ";//刷新单词
}
}
return output;
}
};
2.Bigram分词
[外链图片转存失败(img-FAkjnKc7-1568452381817)(/Users/magicmessi/Desktop/屏幕快照 2019-09-14 上午10.04.32.png)]
基本思路:先将每句话根据空格分成一个个单词,存进一个数组,很容易想到java中的split函数,再遍历数组,将符合的字符存进集合中,最后根据集合大小创建数组,将数组输出。
class Solution{
public String[] findOcurrences(String text, String first, String second){
String[] temp = text.split(" ");//将句子分隔开
List<String> list = new ArrayList<>();//创建一个集合存储需要的对象。
for(int i=0; i<temp.length-2;i++){
if(temp[i].equals(first) && temp[i+1].equals(second)){
list.add(temp[i+2]);
}//从第二个开始,将需要的存进集合
}
String[] output = new String[list.size()];//根据集合的大小创建同等大小的数组。
for(int j=0; j<list.size();j++){
output[j] = list.get(j);//将集合的字符存进数组
}
return output;
}
}
3.叶子相似树
[外链图片转存失败(img-bYPFJL9b-1568452381817)(/Users/magicmessi/Desktop/屏幕快照 2019-09-14 下午2.10.52.png)]
思路:利用递归取出两棵树的叶子存进两个集合,再对两个集合中的对象依次取出进行对比。
java代码:
class Solution{
private List<Integer> list1 = new ArrayList<>();
private List<Integer> list2 = new ArrayList<>();
void get_leaf(TreeNode root,List(Integer) list){
if(root == null) return;
if(root.left == null && root.right==null){
list.add(root.val);
}
get_leaf(root.left,list);
get_leaf(root.rifht,list);//进行递归,取出所有叶子
}
public boolean leafSimilar(TreeNode root1,TreeNode root2){
get_leaf(root1,list1);
get_leaf(root2,list2);
if(list1.size()!=list2.size())//叶子总数进行比较
return false;
for(int i = 0;i<list1.size();i++){
if(list1.get(i)!= list2.get(i))
return false;
}//对每个叶子进行比较
return true;
}
}
4。二叉树中所有距离为k的节点
[外链图片转存失败(img-73xcJVX2-1568452381818)(/Users/magicmessi/Desktop/屏幕快照 2019-09-14 下午3.54.02.png)]
基本想法:后续遍历。代码注释说的比较详细
代码及注释:
class Solution {
public:
vector<int> output;
vector<int> distanceK(TreeNode* root, TreeNode* target, int K) {
//root或者target为空
if (root == NULL || target == NULL){
return {};
}
//K == 0,只有target本身
if (K == 0){
return {target->val};
}
myDFS(root, target, K);//后序遍历二叉树
return ouput;
}
//后序遍历以root为根的二叉树,并且返回root的父节点到target的距离
int myDFS(TreeNode* root, TreeNode* target, int K){
if (root == NULL){
return -1;//返回-1,说明距离无穷大
}
if (root == target){
helper(root, K);//取出以root为根的距离为K的元素
return 1;//root的父节点到target的距离为1
}
//如果target在root的左子树
int distance = myDFS(root->left, target, K);
//更新distance记录的是root->left的父节点root到target的距离
if (distance != -1 && K >= distance){
if (K == distance){//如果root到target的距离刚好为K
output.push_back(root->val);
return -1;
}
else {
//否则搜索root->right距离target == K的节点
//root到target的距离为distance,root->right到target的距离为distance + 1
helper(root->right, K - (distance + 1));
return distance + 1;
}
}
//如果target在root的右子树
distance = myDFS(root->right, target, K);
//更新distance记录的是root->right的父节点root到target的距离
if (distance != -1 && K >= distance){
if (K == distance){//如果root到target的距离刚好为K
output.push_back(root->val);
return -1;
}
else {
//否则搜索root->left距离target == K的节点
//root到target的距离为distance,root->left到target的距离为distance + 1
helper(root->left, K - (distance + 1));
return distance + 1;
}
}
return -1;//否则target到root的父节点的距离无穷大
}
//获取以root为根,到达root的距离为K的节点
void helper(TreeNode* root, int K){
if (root == NULL || K < 0){
return;
}
if (K == 0){
resVec.push_back(root->val);
}
else{
helper(root->left, K - 1);
helper(root->right, K - 1);
}
}
};
5.三角形最小路径和
[外链图片转存失败(img-qcAbV0qM-1568452381818)(/Users/magicmessi/Desktop/屏幕快照 2019-09-14 下午4.18.20.png)]
思路:动态规划,从下往上。从倒数第二行开始,先取得最后一行的最小,再往上,动态规划的式子triangle[i][j]+=min(triangle[i+1][j],triangle[i+1][j+1]
代码及注释:
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int n=triangle.size();// 取得最底层的大小
for(int i=n-2;i>=0;i--){//从倒数第二行开始
for(int j=0;j<triangle[i].size();j++){
triangle[i][j]+=min(triangle[i+1][j],triangle[i+1][j+1]);
}
}
return triangle[0][0];//到最上面时就是所需最小值
}
};