美文网首页
腾讯优图常见算法题(二)

腾讯优图常见算法题(二)

作者: 加油11dd23 | 来源:发表于2021-05-11 23:31 被阅读0次

十九、手撕快排

class Solution {
    int partition(vector<int>& nums, int l, int r) {
        int pivot = nums[r];
        int i = l - 1;
        for (int j = l; j <= r - 1; ++j) {
            if (nums[j] <= pivot) {
                i = i + 1;
                swap(nums[i], nums[j]);
            }
        }
        swap(nums[i + 1], nums[r]);
        return i + 1;
    }
    int randomized_partition(vector<int>& nums, int l, int r) {
        int i = rand() % (r - l + 1) + l; // 随机选一个作为我们的主元
        swap(nums[r], nums[i]);
        return partition(nums, l, r);
    }
    void randomized_quicksort(vector<int>& nums, int l, int r) {
        if (l < r) {
            int pos = randomized_partition(nums, l, r);
            randomized_quicksort(nums, l, pos - 1);
            randomized_quicksort(nums, pos + 1, r);
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        srand((unsigned)time(NULL));
        randomized_quicksort(nums, 0, (int)nums.size() - 1);
        return nums;
    }
};

二十、从前序和中序中构建二叉树

class Solution {
private:
    unordered_map<int, int> index;

public:
    TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
        if (preorder_left > preorder_right) {
            return nullptr;
        }
        
        // 前序遍历中的第一个节点就是根节点
        int preorder_root = preorder_left;
        // 在中序遍历中定位根节点
        int inorder_root = index[preorder[preorder_root]];
        
        // 先把根节点建立出来
        TreeNode* root = new TreeNode(preorder[preorder_root]);
        // 得到左子树中的节点数目
        int size_left_subtree = inorder_root - inorder_left;
        // 递归地构造左子树,并连接到根节点
        // 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
        root->left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);
        // 递归地构造右子树,并连接到根节点
        // 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
        root->right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        // 构造哈希映射,帮助我们快速定位根节点
        for (int i = 0; i < n; ++i) {
            index[inorder[i]] = i;
        }
        return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
    }
};

二十一、数组中重复的数据

二十二、买卖股票的最佳时机

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int inf = 1e9;
        int minprice = inf, maxprofit = 0;
        for (int price: prices) {
            maxprofit = max(maxprofit, price - minprice);
            minprice = min(price, minprice);
        }
        return maxprofit;
    }
};

二十三、爬楼梯

image.png
class Solution {
public:
    int climbStairs(int n) {
        int p = 0, q = 0, r = 1;
        for (int i = 1; i <= n; ++i) {
            p = q; 
            q = r; 
            r = p + q;
        }
        return r;
    }
};

二十四、最长回文子串

image.png
#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.size();
        if (n < 2) {
            return s;
        }

        int maxLen = 1;
        int begin = 0;
        // dp[i][j] 表示 s[i..j] 是否是回文串
        vector<vector<int>> dp(n, vector<int>(n));
        // 初始化:所有长度为 1 的子串都是回文串
        for (int i = 0; i < n; i++) {
            dp[i][i] = true;
        }
        // 递推开始
        // 先枚举子串长度
        for (int L = 2; L <= n; L++) {
            // 枚举左边界,左边界的上限设置可以宽松一些
            for (int i = 0; i < n; i++) {
                // 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得
                int j = L + i - 1;
                // 如果右边界越界,就可以退出当前循环
                if (j >= n) {
                    break;
                }

                if (s[i] != s[j]) {
                    dp[i][j] = false;
                } else {
                    if (j - i < 3) {
                        dp[i][j] = true;
                    } else {
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                }

                // 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置
                if (dp[i][j] && j - i + 1 > maxLen) {
                    maxLen = j - i + 1;
                    begin = i;
                }
            }
        }
        return s.substr(begin, maxLen);
    }
};

二十五、三数之和

image.png
image.png
image.png
#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Solution {
public:
   string longestPalindrome(string s) {
       int n = s.size();
       if (n < 2) {
           return s;
       }

       int maxLen = 1;
       int begin = 0;
       // dp[i][j] 表示 s[i..j] 是否是回文串
       vector<vector<int>> dp(n, vector<int>(n));
       // 初始化:所有长度为 1 的子串都是回文串
       for (int i = 0; i < n; i++) {
           dp[i][i] = true;
       }
       // 递推开始
       // 先枚举子串长度
       for (int L = 2; L <= n; L++) {
           // 枚举左边界,左边界的上限设置可以宽松一些
           for (int i = 0; i < n; i++) {
               // 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得
               int j = L + i - 1;
               // 如果右边界越界,就可以退出当前循环
               if (j >= n) {
                   break;
               }

               if (s[i] != s[j]) {
                   dp[i][j] = false;
               } else {
                   if (j - i < 3) {
                       dp[i][j] = true;
                   } else {
                       dp[i][j] = dp[i + 1][j - 1];
                   }
               }

               // 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置
               if (dp[i][j] && j - i + 1 > maxLen) {
                   maxLen = j - i + 1;
                   begin = i;
               }
           }
       }
       return s.substr(begin, maxLen);
   }
};

二十六、合并两个有序数组

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int p1 = 0, p2 = 0;
        int sorted[m + n];
        int cur;
        while (p1 < m || p2 < n) {
            if (p1 == m) {
                cur = nums2[p2++];
            } else if (p2 == n) {
                cur = nums1[p1++];
            } else if (nums1[p1] < nums2[p2]) {
                cur = nums1[p1++];
            } else {
                cur = nums2[p2++];
            }
            sorted[p1 + p2 - 1] = cur;
        }
        for (int i = 0; i != m + n; ++i) {
            nums1[i] = sorted[i];
        }
    }
};

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        for (int i = 0; i != n; ++i) {
            nums1[m + i] = nums2[i];
        }
        sort(nums1.begin(), nums1.end());
    }
};

相关文章

  • 腾讯优图常见算法题(二)

    十九、手撕快排 二十、从前序和中序中构建二叉树 二十一、数组中重复的数据 二十二、买卖股票的最佳时机 二十三、爬楼...

  • 腾讯优图常见算法题

    最常见的: 一、 两数之和 二、链表反转 三、环状链表 四、快排 五、合并两个有序链表 六、最大子序和 七、最长上...

  • 常见算法题

    1. reserve 让数组反转倒置 2. 排序算法 面试最常考:快速排序和希尔算法 (tips) 原理:如果是想...

  • 二分图

    说说二分图,其实图论的题难点不在用算法,难在如何建图,只有图建好了,剩下的就简单了,在这说说求二分图的算法,即匈牙...

  • 调用腾讯优图识别名片

    钉钉端实现扫名片,调用腾讯优图识别名片信息 调用后台接口获取腾讯优图的请求的url以及请求头请求体,appid,鉴...

  • 2021年腾讯校招季,各事业部算法题 TOP 10,你能手撕几道

    前言 腾讯校招开始了,不知道大家投了吗?这里为大家整理了腾讯6大事业群校招常问算法题TOP 10 算法题榜,希望能...

  • autojs人像变换

    牙叔教程 简单易懂 产品简介 腾讯云神图·人像变换(Face Transformation)基于腾讯优图领先的人脸...

  • 【微信事业群】趣味面试算法题

    今天和大家分享博主在腾讯二面期间遇到的两道比较有意思的算法题,由Excel引出的两道面试算法题,可以点开上面的音乐...

  • 翻转二叉树(Java)

    翻转二叉树 对于此题而言,我们使用深度优先算法来遍历二叉树。 1、深度优先算法是根据二叉树的路径进行遍历2、广度优...

  • 程序员进阶之算法练习(三十四)LeetCode专场

    前言 LeetCode上的题目是大公司面试常见的算法题,今天的目标是拿下5道算法题:1、2、3题都是Medium的...

网友评论

      本文标题:腾讯优图常见算法题(二)

      本文链接:https://www.haomeiwen.com/subject/allodltx.html