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

  • 相关阅读:
    LeetCode 453 Minimum Moves to Equal Array Elements
    LeetCode 112 Path Sum
    LeetCode 437 Path Sum III
    LeetCode 263 Ugly Number
    Solutions and Summay for Linked List Naive and Easy Questions
    AWS–Sysops notes
    Linked List
    All About Linked List
    datatable fix error–Invalid JSON response
    [转]反编译c#的相关问题
  • 原文地址:https://www.cnblogs.com/lfri/p/15707608.html
Copyright © 2011-2022 走看看