zoukankan      html  css  js  c++  java
  • 微软面试算法题(整理)

    都是来自牛客网面经,主要侧重于非leetcode题

    1.

    题目:2n个数的数组,[1,1,2,2,…,n,n],输出所有可能的数组集合,使前面非递减后面非递增

    首先一种暴力的做法,从中任选n个,排序,总能满足要求,只是太慢了。

    假如我们考虑n个数的成分,比如有几个1,几个2,....几个n,只要满足个数和为n,这样都不用排序了

    dfs写一下就好了,也可以写个三进制枚举

    而且我们还可以直接求得个数,使用组合数学,每个数字有0,1,2三种个数,要求总个数为n,因此方案数是 \((1+x+x^2)^n\)\(x^n\) 项的系数

    int cnt = 0; // (1+x+x^2)^n 的x^n项的系数,也是最大系数
    // 枚举到第i个,sum是 前面个数和,
    void dfs(int n, int i, vector<int>& path, int sum) {
        // cout << "i: " << i << " " << sum << endl;
        if(i == n ) {
            if(sum == n) {
                for(int j = 0; j < n; j++) {
                    for(int k = 0; k < path[j]; k++) {
                        cout << j+1;
                    }
                }
                cnt++;
                cout << endl;
            }
            return;
        }
        for(int j = 0; j <= 2; j++) {
            if(sum+j > n)  break;
            path[i] = j;
            dfs(n, i + 1, path, sum+j);
            // path[i] = 0;
        }
        return;
    }
    
    

    2.

    题目:现在有一部电梯,在某一楼层N,你只可以乘坐这个电梯向上或者向下K层(K是N的所有因子), 给定当前楼层i和目标楼层j,求最少需要乘坐多少次电梯从当前楼层到达目标楼层。

    第一眼思路是记忆化搜索,然后写完发现,会出现相互依赖进入死循环。

    反过来想,从目标层j出发,dp[j]=0,然后更新一步之内能到达的并加入队列,再拿这一批去更新....
    按理说可以一层一层更新,为了编码方便,我使用的优先队列,能次取最小的出来更新
    这种贪心的正确性 和 Dijsktra算法类似

    int short_elevator(int n, int i, int j) {
        vector<int> factors = factor(n);   // 求N的所有因子
        vector<int> dp(n, -1);
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
        pq.push(make_pair(0, j));
        dp[j] = 0;
        while(!pq.empty()) {
            int val = pq.top().first;
            int cur = pq.top().second;
            cout << "val: " << val << " cur: " << cur << endl;
            pq.pop();
            if(cur == i)  return pq.top().first;
            for(int k = 0; k < factors.size(); k++) {
                int next = cur + factors[k];
                if(next <= n && dp[next] == -1)  pq.push(make_pair(val+1, next));
                next = cur - factors[k];
                if(next >= 1 && dp[next] == -1)  pq.push(make_pair(val+1, next));
            }
        }
        return -1;  // 到不了为-1,因为因子存在1,肯定能到
    }
    

    害,就是最短路,能互达的两层之间连边,求i到j的最短路,但是边权都是1;
    由于边权为1,前面更新的一定是最短路,不会被再次更新,因此可以用dp[next] == -1判断;
    由于边权为1,直接BFS就行...啊这这都没看出来,菜哭,都不用上优先队列;

    我这写的啥,BFS和Dijkstra混杂??

    3.

    题目:1. 给定一个源字符串a,一个目标字符串b,一个替代字符串c。将a中的b更换为c。例:a="Hello, world", b=" ", c="%2b",则替换后a变为"Hello,%2bworld"
             - 最优解应该用KMP算法 ,我现场用了暴力双指针。
             - 面试官说考这道题的意义是数组扩容什么的,我没懂……

    思路:数组填充题,先扩容在移动. i指向新长度的末尾,j指向旧长度的末尾。
    其实这是leetcode 剑指 Offer 05. 替换空格
    参考 替换空格题解

    class Solution {
    public:
        string replaceSpace(string s) {
            int n = s.size();
            int cnt = 0;  // 统计空格的个数
            for(int i = 0; i < n; i++) {
                if(s[i] == ' ')  cnt++;
            }
            s.resize(n+cnt*2);
            int j = n+cnt*2-1;
            for(int i = n-1; i >= 0; i--) {
                if(s[i] == ' ') {
                    s[j--] = '0';
                    s[j--] = '2';
                    s[j--] = '%';
                    // cnt++;
                } else {
                    s[j--] = s[i];
                }
            }
            return s;
        }
    };
    

    4.

    题目:
    00001.最大子数组和(LeetCode原题,n时间1空间)

    1. 两个长度为m的无序数组A,B,对于任意不相交的区间ab和cd,val[ab]=sum(A,a,b)- sum(B,a,b),val[cd] = sum(B,c,d)- sum(A,c, d)
      求abcd,使val[ab] + val[cd]最大 (这题比较难,先写了个暴力解法,然后和面试官逐步讨论优化,没有给出最优解法)

    第一题很简单,dp[i] 表示以i结尾的最大子数组,省掉数组可以用一个变量表示

    1. 最大子数组和
    class Solution {
    public:
        int maxSubArray(vector<int>& nums) {
            if(nums.size() == 0)  return 0;
            int sum = 0, ans = nums[0];
            for(int i = 0;i < nums.size();i++) {
                sum = (sum<0 ? 0 : sum) + nums[i]; // 条件表达式记得加括号
                ans = max(ans, sum);
            }
            return ans;
        }
    };
    

    第二题,看起来比较难,既然有两小份,是不是暗示了什么??

    假设[a,b] 与 [c,d] 从i 分开,val[ab] + val[cd]的最大值就是val[ab]在i之前找最大值,val[cd]在i之后找最大值,

    val[ab]=sum(A,a,b)- sum(B,a,b),如果我们将A对应的元素减去B,不就是新数组的最大子数组问题了嘛

    同理val[cd] 可以用B减A

  • 相关阅读:
    nodejs获取服务器数据到页面
    Struts 2
    JQuery
    JDBC
    Hiberbate
    EasyUi
    JavaScript
    利用 HashSet 去过滤元素是否重复
    HTML
    MySQL
  • 原文地址:https://www.cnblogs.com/lfri/p/15707608.html
Copyright © 2011-2022 走看看