【LeetCode】Array Topic总结

来源:互联网 发布:淘宝贝南海幼儿园应聘 编辑:程序博客网 时间:2024/05/22 22:50

【LeetCode】717. 1-bit and 2-bit Characters

/*基本思路就是1位1位往后探测,看当前位置往前的所有位是否能够组成满足要求的字符串因为最后一位是0,所以只要判断前n-1位能否组成满足要求的字符串即可*/class Solution {public:    bool isOneBitCharacter(vector<int>& bits) {        auto len = bits.size();        if (len == 1) return true;        vector<bool> vb(len, false); // vb记录当前位置及之前的位能够组成字符串        // 为vb[0]和vb[1]赋初值,简单分析一下就知道取值情况        vb[0] = 1 - bits[0];        if (bits[1] == 0) vb[1] = true;        else vb[1] = bits[0];        for (int i = 2; i < len; ++i) {            if (bits[i]) { // 当前位是1,则前一位必须也为1,同时前i-2位能组成字符串                vb[i] = (bits[i-1] == 1) && vb[i-2];            } else { // 当前位是0,则前一位为1,同时前i-2位能组成字符串,或者前i-1位能组成字符串                vb[i] = vb[i-1] || ((bits[i-1] == 1) && vb[i-2]);            }        }        // 判断前n-1个位能够组成字符串,即为我们的答案        return vb[len-2];    }};

【LeetCode】 695. Max Area of Island

/*递归。只要找到1的位置,就进行深搜,找到所有相邻的1,同时记录1的个数,即为岛的大小*/class Solution {public:    // x,y是1的位置,res记录1的个数,r,c为grid的行数和列数    void depth(vector<vector<int>>& grid, int x, int y, int &res, const int& r, const int& c) {        ++res; // 记录1的个数        grid[x][y] = 0; // 标记访问,将当前位置清0        if (x-1 >= 0 && grid[x-1][y] == 1) depth(grid, x-1, y, res, r, c);        if (x+1 < r  && grid[x+1][y] == 1) depth(grid, x+1, y, res, r, c);        if (y-1 >= 0 && grid[x][y-1] == 1) depth(grid, x, y-1, res, r, c);        if (y+1 < c  && grid[x][y+1] == 1) depth(grid, x, y+1, res, r, c);    }    int maxAreaOfIsland(vector<vector<int>>& grid) {        int r = grid.size();        if (r == 0) return 0;        int c = grid[0].size();        int maxres = 0;        for (int i = 0; i < r; ++i) {            for (int j = 0; j < c; ++j) {                if (grid[i][j]) { // 找到一个1,进行深搜                    int t = 0;                    depth(grid, i, j, t, r, c);                    if (t > maxres) maxres = t; // 更新最大值                }            }        }        return maxres;    }};

【LeetCode】667. Beautiful Arrangement II

/*题目让构造一个1到n的排列,且相邻两个数差的绝对值正在能够取遍1到k。考虑如果前k+1个数正好能组成满足要求的排列,后面的数按顺序排列就好,因为他们的差绝对值为1。考虑这样一个排列,1,k+1,2,k,3,k-1,...,则差得绝对值正好为k,k-1,k-2,k-3,k-4,即使用前1到k+1就能够构造出满足要求的排列*/class Solution {public:    vector<int> constructArray(int n, int k) {        vector<int> res;        for (int i = 1; i <= k + 1; ++i) {            // 接下面两行判断什么时候结束构造            if (i == k + 2 - i) { res.push_back(i); break; }            if (i > k + 1 - i) break;            res.push_back(i);            res.push_back(k + 2 - i);        }        // 剩下的数按顺序排列就好        for (int i = k + 2; i <= n; ++i) res.push_back(i);        return res;    }};

【LeetCode】560. Subarray Sum Equals K

/*一个方法是使用前缀和每个位置之前所有数的和,然后再遍历每个区间,前缀和相减得到区间和,判断是够等于k,但这个方法的时间复杂度为O(n*n),太高了。根据前面做题的经验,关于求和的问题,通常会固定一个值,然后找另一个值。应用到本题,就是固定一个前缀和,找到与其相差k的另一个前缀和,具体看代码*/class Solution {public:    int subarraySum(vector<int>& nums, int k) {        // 特殊情况处理,本题其实不需要        if (nums.size() == 0) return 0;        if (nums.size() == 1) return (nums[0] == k) ? 1 : 0;        // 使用map帮助查找        unordered_map<long long, int> m;        int sumx = 0; // 记录前缀和        int res = 0;        ++m[0]; // 考虑区间是从第一个数开始的情况        for (int i = 0; i < nums.size(); ++i) {            sumx += nums[i];   // 记录区间和            res += m[sumx-k];  // 找到前面出现过的和为sumx-k的次数            ++m[sumx];         // 更新map        }        return res;    } };

【LeetCode】169. Majority Element

/*让找出出现次数超过n/2的数。考虑如果存在这样的数,则它与其他数抵消之后,最后数组中肯定只剩它自己,据此有以下代码*/**class Solution {public:    int majorityElement(vector<int>& nums) {        int cnt = 0; // 当前数有几个        int res = nums[0];        for (auto x : nums) {            if (cnt == 0) { // 说明之前的数都抵消掉了                res = x; // 记录一个新数                ++cnt;            } else {                if (x == res) ++cnt; // 更新当前数的次数                else --cnt;      // 抵消掉            }        }        return res;    }};

【LeetCode】53. Maximum Subarray

/* 动态规划问题,考虑dp[n]表示以第n个数为结尾的最大和,则dp[n+1]只有两种选择,要么=dp[n]+a[n+1],要么=a[n+1],即=max(dp[n]+a[n+1], a[n+1]),空间复杂度和时间负责度都为O(n),空间复杂度可以优化到O(1) */class Solution {public:    int maxSubArray(vector<int>& nums) {        int sumx = 0; // sumx记录以当前数为结尾的最大和        if (nums.size() == 0) return 0;        int maxsum = nums[0];        for (int x : nums) {            sumx = max(sumx + x, x); // 更新,只与前一个状态的最大和有关            if (sumx > maxsum) maxsum = sumx;        }        return maxsum;    }};

【LeetCode】611. Valid Triangle Number

/* 首先进行排序,然后选择一条最大边,只要剩下两条边的和比最大边大就能组成三角形,由于已经有序,查找起来很方便 */class Solution {public:    int triangleNumber(vector<int>& nums) {        if (nums.size() < 3) return 0;        sort(nums.begin(), nums.end()); // 排序        int res = 0;        int n = nums.size();        for (int i = n-1; i >= 0; --i) {            int j = 0, k = i - 1; // 最大边位置i,剩下两条位置为j和k            while (j < k) {                // 两边之和太小,只能增加最短边                if (nums[j] + nums[k] <= nums[i]) ++j;                 // j满足要求,则j到k-1的所有边,都能和k和i两条边组成三角形,即找到了所有中间边为nums[k]的情况                // 然后考虑中间边为nums[k-1]的情况,而j无需更新,                else res += (k-j), --k;            }        }        return res;    }};