头条面试题

-w150

待处理

  1. 极大似然的原理
  2. SVM 原理
  3. L1和L2的区别,以及各自的使用场景
  4. 为什么梯度是函数变化最快的方向 https://zhuanlan.zhihu.com/p/24913912

去除字符串连续字符

递归的去除字符串中连续的 ac 和 b

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

int main() {
    string s {"aaccaptgbcaca"};
    if (s.empty()) {
        return 0;
    }
    stack<char> st;
    int cursor = 0;
    while(cursor < s.size()) {
        char ch = s[cursor++];
        if (st.empty()) {
            st.push(ch);
        } else {
            if ( ch == 'b') {
                continue;
            } else if (st.top() == 'a' && ch == 'c') {
                st.pop();
            } else {
                st.push(ch);
            }
        }
    }

    vector<char> ch(st.size());
    for (int i = st.size()-1; i >= 0; i--) {
        ch[i] = st.top();
        st.pop();
    }

    for (auto& e : ch) {
        cout << e << " ";
    }
    return 0;

}

将一个字符串变成数字

#include <iostream>
#include <sstream>

using namespace std;

int main() {
    string s = " 1234js9";
    stringstream ss {s};
    int num;
    ss >> num;
    cout << num << endl;
    return 0;
}

链表加法

leetcode 2

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode dummyHead(-1);
        // 凡是这种要构建新链表的, 貌似都要搞一个 dummyHead 比较简单
        ListNode *p = &dummyHead;
        int partSum = 0;
        while (l1 != nullptr || l2 != nullptr) {
            if (l1) {
                partSum += l1->val;
                l1 = l1->next;
            }
            if (l2) {
                partSum += l2->val;
                l2 = l2->next;
            }
            p->next = new ListNode(partSum%10);
            p = p->next;
            partSum /= 10;     
        }
        
        if (partSum != 0) p->next = new ListNode(partSum);
        return dummyHead.next;
    }
};

判断二叉树是不是二叉搜索树

leetcode98. Validate Binary Search Tree

方法 1

中序遍历树, 查看遍历过程中是否是升序

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode* root) {
        TreeNode* p = root;
        if (!root) return true;
        stack<TreeNode*> st;
        long pre = LONG_MIN;
        long cur = LONG_MIN;
        bool isValid = true;
        while (p || !st.empty()) {
            if (p) {
                st.push(p);
                p = p->left;
            } else {
                cur = st.top()->val;
                if (cur <= pre) {
                    isValid = false;
                    break;
                }
                pre = cur;
                p = st.top()->right;
                st.pop();
            }
        }
        return isValid;
    }  
};

方法 2

根节点的值大于左子树的最大值, 小于右子树的最小值,
作为叶子节点来说, 以左叶子节点来说, 左叶子节点要

  1. 满足父节点的约束;
  2. 小于其父节点的值;
class Solution {
public:
    bool isValidBST(TreeNode* root) {
        return isValidBST(root, LONG_MIN, LONG_MAX);
    }
    
    bool isValidBST(TreeNode* root, long min_val, long max_val) {
        if (!root) return true;
        return (root->val > min_val) && (root->val < max_val) &&
            (isValidBST(root->left, min_val, root->val)) &&
            (isValidBST(root->right, root->val, max_val));
    }   
};

将二叉搜索树转换成双向链表

递归解法

解法很经典, 好好揣摩.

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
#include<iostream>
#include<stack>
using namespace std;

class Solution {
public:
    TreeNode* res;
    TreeNode* Convert(TreeNode* pRootOfTree)
    {
        if(pRootOfTree == nullptr) return nullptr;
        TreeNode* pre = nullptr;
        convertHelper(pRootOfTree, pre);
        return res;
    }
    
    // *& 很重要, 必须使用引用, 否则当前 pre 并没有更新到最新位置
    void convertHelper(TreeNode* cur, TreeNode*& pre)  
    {
        if(cur == nullptr) return;
         
        convertHelper(cur->left, pre);
         
        cur->left = pre;
        if(pre) {
            pre->right = cur;  // 用于处理链表的起始位置
        } else {
            res = cur;
        }
        pre = cur;
        convertHelper(cur->right, pre);
    }
};

非递归解法

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
#include<iostream>
#include<stack>
using namespace std;

class Solution {
public:
    TreeNode* Convert(TreeNode* pRootOfTree) {
        if (!pRootOfTree) {
            return nullptr;
        }
        TreeNode DummyHead(-1);
        TreeNode *dp = &DummyHead;
        TreeNode *p = pRootOfTree;
        stack<TreeNode*> st;
        while (p || !st.empty()) {
            if (p) {
                st.push(p);
                p = p->left;
            } else {
                p = st.top();
                st.pop();
                dp->right = p;
                p->left = dp;
                dp = p;
                p = p->right;
            }
        }
        DummyHead.right->left = nullptr;
        return DummyHead.right;
    }
};

他人秋招三面通过面经

用了同学的白金内推码,所以直接进入了面试,全程都在写题!机器学习的问题非常少!
一面:
1、介绍项目
2、强化学习PG的推导
3、强化学习DQN,DDQN,AC,DDPG的区别
4、n个[0,n)的数,求每个数的出现次数(不能开辟额外空间)
5、K个有序数组,找一个长度最小的区间,在这个区间里至少包含每个数组各一个数。
分析:初始化带下为K的最小堆,K个数字是每个数组中的最小值,设置变量max记录k个数字中的最大值,删除堆顶元素,将原堆顶元素对应的数组中下一个元素加入到堆中,调整堆,并且记录当前区间范围为(max-min),重复执行直到某个数组所有值都被删除。

二面
1、介绍DQN的项目
2、数组的全排列(空间复杂度O(1))
数组中有重复元素,所以我们需要一个Set保存已经出现过的排列。因此我先写了一个回溯的方法,可是空间复杂度比较高,面试官说能不能用O(1)的空间复杂度,全排列直接print出来就行。即我们不需要保存已经出现过什么排列。这需要对数组先进性排序。
3、两堆钞票,尽可能均分(利用背包问题的思想)
想了半天,写出来一个深度优先搜索的算法。面试官提示我可以考虑从背包问题的角度出发,但最后也没想出来。

三面:
1、无向无环图中,最短路径的最大值(O(n^3)的解法)
这里考察的其实就是Floyd算法。哎,只可惜自己当时没有复习图的相关算法,完全不会写呀。
算法思想原理:Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。
从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。
2、LSTM的公式
3、RNN为什么出现梯度消失
4、BPTT的推导。

posted @ 2018-08-22 21:38  nowgood  阅读(2546)  评论(0编辑  收藏  举报