自用力扣笔记备忘录——数组tag简单题

  • 想来想去还是决定写在csdn,本地的移动性不太好
  • 此备忘录自用为住,方便本人复习用的
  • 方法1为本人自己写的,其他的均有参考
  • 目录若无方法一只有方法二,则是没写出来;
  • 如果没有方法N小标题说明这个题官方解法和我的一样或者官方方法遥不可及。
  • 题目来自https://leetcode-cn.com/tag/array/,所有简单题,按照题号顺序刷的
  • 目前刷到了第7页(一共14页)应该不打算刷这一部分了

目录

  • 数组tag
    • 1. 两数之和
      • 方法一:
      • 方法二:无序表
    • 26. 删除排序数组中的重复项
    • 27. 移除元素
      • 方法一:
      • 方法二:巧妙の双指针
    • 35. 搜索插入位置
      • 方法二
    • 53. 最大子序和
      • 方法二:DP
    • 66. 加一
      • 方法一:
      • 方法二:
    • 88. 合并两个有序数组
      • 方法二:三指针
    • 118. 杨辉三角
    • 121. 买卖股票的最佳时机
      • 方法二:
    • 122. 买卖股票的最佳时机 II
      • 方法二:
      • 方法三
    • 167. 两数之和 II - 输入有序数组
    • 169. 多数元素
      • 方法一:
      • 方法二:打擂台
    • 217. 存在重复元素
      • 方法一:
      • 方法二:unordered_set
    • 219. 存在重复元素 II
    • 228. 汇总区间
      • 方法二
    • 268. 丢失的数字
      • 方法一:
      • 方法二:位运算
      • 方法三:位运算
    • 283. 移动零
    • 448. 找到所有数组中消失的数字
      • 方法一
      • 方法二
    • 485. 最大连续1的个数
    • 509. 斐波那契数
      • 方法一
      • 方法二:滚动数组
    • 561. 数组拆分 I
    • 566. 重塑矩阵
    • 605. 种花问题
    • 方法二
    • 628. 三个数的最大乘积
      • 方法一
      • 方法二:一句话
      • 方法三:归纳情况
    • 643. 子数组最大平均数 I
      • 方法二:滑动窗口
    • 665. 非递减数列
    • 674. 最长连续递增序列
    • 697. 数组的度
    • 717. 1比特与2比特字符
      • 方法二:
    • 724. 寻找数组的中心索引
      • 方法一:
      • 方法二
    • 747. 至少是其他数字两倍的最大数
    • 766. 托普利茨矩阵
      • 方法二
    • 830. 较大分组的位置
    • 832. 翻转图像
    • 867. 转置矩阵
    • 888. 公平的糖果棒交换
      • 方法二
    • 905. 按奇偶排序数组
    • 914. 卡牌分组
      • 方法二:
    • 922. 按奇偶排序数组 II
    • 941. 有效的山脉数组
    • 985. 查询后的偶数和
    • 989. 数组形式的整数加法
      • 方法二
      • 方法三
    • 999. 可以被一步捕获的棋子数
    • 1002. 查找常用字符
      • 方法二
    • 1013. 将数组分成和相等的三个部分
      • 方法一:包含加速代码
    • 1018. 可被 5 整除的二进制前缀
      • 方法一:
    • 方法二:左移一位+只保留余数
    • 1051. 高度检查器
    • 1089. 复写零
      • 方法一:迭代器在insert里的失败运用
        • 解决方法一:
        • 解决方法二:
      • 方法二
    • 1122. 数组的相对排序
      • 方法二:计数排序
    • 1128. 等价多米诺骨牌对的数量
      • 方法二:计数排序
    • 1160. 拼写单词
      • 方法二:char和int转换

数组tag

1. 两数之和

  • 给数组,找两个加起来等于target的数字。
  • https://leetcode-cn.com/problems/two-sum/

示例 1:

输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] ==
9 ,返回 [0, 1] 。

方法一:

双指针法

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
    //先排序nums,
    //再找到nums[0]下和大于target的最小end,start为0
    //重复上述过程,在start和end之间寻找并更新start&end
    
    vector<int> ans;
    vector<int> temp(nums);
    sort(temp.begin(),temp.end());
    
    int e=temp.size()-1;
    int i=0;
    
    while(i<e && temp[i]+temp[e]!=target)
    {
        if(temp[i]+temp[e]>target)
            e--;
        else if(temp[i]+temp[e]<target)
            i++;
    }
    if(temp[i]+temp[e]==target && i<e){
        int j=0;
        while(j<nums.size()){
            if(nums[j]==temp[i] ||nums[j]==temp[e])
                ans.push_back(j);
            j++;
        }
        return ans;
        }
    return ans;
    }
};

方法二:无序表

注意无序表用法
https://blog.csdn.net/qq_42147816/article/details/104452663#t50


//将所有元素放入查找表,之后对于每一个元素 a,查找 target - a 是否存在
//使用了无序表
class Solution
{
public:
    vector<int> twoSum(vector<int>& nums, int target)
    {
        unordered_map<int,int> um;
        vector<int> res;
        for (int i = 0; i < nums.size(); ++i)
        {
            // 如果能在um中找到值为target-nums[i]的元素
            if (um.find(target-nums[i])!=um.end())
            {
                res.push_back(i);
                res.push_back(um[target-nums[i]]);
                return res;
            }
            // 找不到就继续从num读一个数进去
            um[nums[i]] = i;
        }
        return res;
    }
};

//链接:https://leetcode-cn.com/problems/two-sum/solution/cjie-fa-su-du-ji-bai-98-by-zhu-que-3-mvdh/

26. 删除排序数组中的重复项

  • 原地删除重复项
  • https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
    
    int cnt=0;
    int ans=1;
    int n=nums.size();
    if(n==0)    return 0;
    for(int i=1;i<n;i++){
        if(nums[i]==nums[i-1])
            cnt++;
        else
        {
            nums[i-cnt]=nums[i];
            ans++;
        }
    }
    return ans;
    }
};

27. 移除元素

需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

方法一:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {

    int cnt=0;
    int step=0;
    int n=nums.size();
    for(int i=0;i<n;i++){
        if(nums[i]==val)
            step++;
        else
            nums[i-step]=nums[i];
    }
    return n-step;

    }
};

方法二:巧妙の双指针

  • 伤害不大但侮辱性极强的官方解法
  • 双指针,n指向末尾不断迭代,和val相等的值会被交换,然后忽略
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {

    int i=0;
    int n=nums.size();
    while (i < n) {
        if (nums[i] == val) {
            nums[i] = nums[n - 1];
            // reduce array size by one
            n--;
            // 注意i没有增加
        } else {
            i++;
        }
    }
    return n;
    }
};

35. 搜索插入位置

  • 在排序数组中找到目标值,并返回其索引,或者其插入位置
  • https://leetcode-cn.com/problems/search-insert-position/

方法二

  • 插入位置的下标是 大于等于 target 的元素的位置。因此,严格小于 target 的元素一定不是解
  • 模板思路,下标一定不能搞错
class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {

    int size = nums.size();
        if (size == 0) {
            return 0;
        }

        int left = 0;
        // 因为有可能数组的最后一个元素的位置的下一个是我们要找的,故右边界是 len
        int right = size;

        while (left < right) {
            int mid = left + (right - left) / 2;
            // 小于 target 的元素一定不是解
            if (nums[mid] < target) 
                // 下一轮搜索的区间是 [mid + 1, right]
                left = mid + 1;
             else 
                right = mid;         
        }
        return left;
    }
};

53. 最大子序和

  • 找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
  • https://leetcode-cn.com/problems/maximum-subarray/

方法二:DP

  • 采用动态规划,以子序列的结束节点为基准,先遍历出以某个节点为结束的所有子序列,因为可以产生递推关系, 采用动态规划时, 经常通过此种遍历方式,如 背包问题, 最大公共子串 , 这里的动态规划解法也是以 先遍历出 以某个节点为结束节点的所有子序列 的思路
// https://leetcode-cn.com/problems/maximum-subarray/solution/xiang-xi-jie-du-dong-tai-gui-hua-de-shi-xian-yi-li/

class Solution {
public:
    // dp法
    int maxSubArray(vector<int>& nums) {

    //类似寻找最大最小值的题目,初始值一定要定义成理论上的最小最大值
        int result = INT_MIN;
        int numsSize = int(nums.size());
        //dp[i]表示nums中以nums[i]结尾的最大子序和
        vector<int> dp(numsSize);
        dp[0] = nums[0];
        result = dp[0];
        for (int i = 1; i < numsSize; i++)
        {
            dp[i] = max(dp[i - 1] + nums[i], nums[i]);
            // 时时更新result
            result = max(result, dp[i]);
        }

        return result;
// https://leetcode-cn.com/problems/maximum-subarray/solution/zui-da-zi-xu-he-cshi-xian-si-chong-jie-fa-bao-li-f/
    }
};

66. 加一

  • 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。最高位数字存放在数组的首位, 数组中每个元素只存储单个数字
  • https://leetcode-cn.com/problems/plus-one/

方法一:

按部就班的写,非常冗长

class Solution {
public:
    vector<int> plusOne(vector<int>& digits) {

    int n=digits.size();
    if(digits[n-1]!=9)   {
        digits[n-1]+=1;
        return digits;
    }
    
        int i=n-1;
        int temp=digits[i];
        while(i>0 && temp==9){
            digits[i] = 0;
            temp=digits[i-1];
            digits[i-1]+=1;
            i--;
        }
        if(i==0 && temp==9)
        {
            //这个赋值只是为了包括9这个例子
            digits[i] = 0;
            digits.insert(digits.begin(),1);
        }
        return digits;
    }
};

方法二:

非常简练

class Solution {
public:
    vector<int> plusOne(vector<int>& digits) {

   int len = digits.size();
        for(int i = len - 1; i >= 0; i--) {
            digits[i]++; // 最初的+1 或者进位
            // 简练!
            digits[i] %= 10;
            // 129或者123这样的数字在这里退出
            if(digits[i]!=0)
                return digits;
        }
        //到这里才退出说明是999这样的数字
        digits.insert(digits.begin(),1);
        return digits;

// https://leetcode-cn.com/problems/plus-one/solution/hua-jie-suan-fa-66-jia-yi-by-guanpengchn/
    }
};

88. 合并两个有序数组

  • 请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
  • https://leetcode-cn.com/problems/merge-sorted-array/

方法二:三指针

  • 官方解答非常nice:指针从尾部倒着进行移动
  • 三指针:指针一p1:nums1有效元素尾部;指针二p2:nums2尾部;指针三p3:最终数组尾部
  • 分3种情况
//官方解答非常nice
class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        // 三指针 指针一p1:nums1有效元素尾部;指针二p2:nums2尾部;
        //指针三p3:最终数组尾部
        // 1.when p1>=0时, compare nums[p1] with nums[p2]
        // 1.1 if nums[p1] is larger,put nums[p1] into p3 then p1--,p3--
        // 1.2 if nums[p2]>=nums[p1],put nums[p2] into p3 then p2--,p3--
        // 2.when p1<0, put nums[p2] into p3 then p2--,p3--
        // End when: p2<0
        // 注意!p3的初始值是m+n-1,覆盖nums1无所谓!
        int p1=m-1,p2=n-1,p3=m+n-1;
        while(p2 >= 0){
            if(p1 >= 0 && nums1[p1] > nums2[p2]){
                nums1[p3--] = nums1[p1--];
            } else {
                nums1[p3--] = nums2[p2--];
            }
        }
    }
};

118. 杨辉三角

  • https://leetcode-cn.com/problems/pascals-triangle/
  • 方法一:注意二维数组如何规定行列的大小。
class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        // 必须带空格
        vector<vector<int> > ans(numRows);//设置行数
    int n=0;
    for(int i=0;i<numRows;i++){
        // 注意二维数组的写法,这里resize每一行的大小
        ans[i].resize(i + 1);
        ans[i][0]=1;
        ans[i][i]=1;
        for(int j=1;j<i;j++)
            ans[i][j]=ans[i-1][j-1]+ans[i-1][j];
    }
    return ans;
    }
};

121. 买卖股票的最佳时机

  • 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
  • https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/

方法二:

DP:dp[i][0] 下标为 i 这天结束的时候,不持股,手上拥有的现金数
dp[i][1] 下标为 i 这天结束的时候,持股,手上拥有的现金数

class Solution {
public:
    // dp
    int maxProfit(vector<int>& prices) {
        int len = prices.size();
        // 特殊判断
        if (len < 2) 
            return 0;
        int dp[len][2];

        // dp[i][0] 下标为 i 这天结束的时候,不持股,手上拥有的现金数
        // dp[i][1] 下标为 i 这天结束的时候,持股,手上拥有的现金数

        // 初始化:不持股显然为 0,持股就需要减去第 1 天(下标为 0)的股价
        dp[0][0] = 0;
        dp[0][1] = -prices[0];

        // 从第 2 天开始遍历
        for (int i = 1; i < len; i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = max(dp[i - 1][1], -prices[i]);
        }        
        return dp[len-1][0];
//https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/bao-li-mei-ju-dong-tai-gui-hua-chai-fen-si-xiang-b/
    }
};

122. 买卖股票的最佳时机 II

  • 你可以尽可能地完成更多的交易(多次买卖一支股票)。但不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
  • https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/

方法二:

贪心算法:每天都买,每天都卖,亏则不买,赚就买。

// 每天都买&每天都卖,亏则不买,赚就买。
class Solution {
public:
    int maxProfit(vector<int>& prices) {
       int profit = 0;
        for (int i = 1; i < prices.size(); i++) {
            int tmp = prices[i] - prices[i - 1];
            if (tmp > 0) profit += tmp;
        }
        return profit;
    }};
// https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/best-time-to-buy-and-sell-stock-ii-zhuan-hua-fa-ji/

方法三

DP,但是很显然没有方法二nice

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        int dp[n][2];
        dp[0][0] = 0, dp[0][1] = -prices[0];
        for (int i = 1; i < n; ++i) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
        }
        return dp[n - 1][0];
    }
};
//https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-ii-by-leetcode-s/

167. 两数之和 II - 输入有序数组

  • 已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
  • https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/
class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
    vector<int> ans;
    int i=0,j=numbers.size()-1;

    while(i!=j){
        if(numbers[i]+numbers[j]==target){
            ans.push_back(i+1);
            ans.push_back(j+1);
            break;
        }
        if(numbers[i]+numbers[j]<target)
            i++;
        if(numbers[i]+numbers[j]>target)
            j--;
    }
    return ans;
}
};

169. 多数元素

  • 多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
  • https://leetcode-cn.com/problems/majority-element/

方法一:

按部就班的方法

class Solution {
public:
    int majorityElement(vector<int>& nums) {

    int n=nums.size();
    int major=nums[0];
    int cnt=1;
    if(n!=1)    
   {for(int i=1;i<n;i++){
        if(nums[i]==major)
            cnt++;
        else if(nums[i]!=major && cnt==0){
            cnt=1;
            major=nums[i];
        }
        else if(nums[i]!=major && cnt!=0){
            cnt--;
        }
    }
    }
    return major;
    }
};

方法二:打擂台

hash+打擂台避免最后遍历,不断与cnt比较并且更新

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        unordered_map<int, int> counts;
        int majority = 0, cnt = 0;
        for (int num: nums) {
            ++counts[num];
            //打擂台避免最后遍历
            if (counts[num] > cnt) {
                majority = num;
                cnt = counts[num];
            }
        }
        return majority;
    }
};
//https://leetcode-cn.com/problems/majority-element/solution/duo-shu-yuan-su-by-leetcode-solution/

217. 存在重复元素

  • 判断是否存在重复元素。
  • https://leetcode-cn.com/problems/contains-duplicate/

方法一:

  • 使用 unordered_map
class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_map<int,int> st;
        int n=nums.size();
        for(int i=0;i<n;i++){
            if((++st[nums[i]]) > 1)
                return true;
        }
        return false;
    }
};

方法二:unordered_set

  • 使用unordered_set
  • 注意for (int x: nums)的写法
class Solution {
public:
    // ²»ÓÃhashÓÃset
    bool containsDuplicate(vector<int>& nums) {
        unordered_set<int> s;
        for (int x: nums) {
            if (s.find(x) != s.end()) {
                return true;
            }
            s.insert(x);
        }
        return false;
    }
};
//https://leetcode-cn.com/problems/contains-duplicate/solution/cun-zai-zhong-fu-yuan-su-by-leetcode-sol-iedd/

219. 存在重复元素 II

  • 值不仅要一样,而且下标 i 和 j 的差的 绝对值 至多为 k。
  • https://leetcode-cn.com/problems/contains-duplicate-ii/
  • 方法一:无难度
class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        unordered_map<int,int> st;
        int n=nums.size();

        for(int i=0;i<n;i++){
            if(st.find(nums[i])!=st.end()){
                int temp=i - st[nums[i]];
                if(temp<=k) return true;
                else st[nums[i]]=i;
            }
            else st[nums[i]] = i;
        }
        return false;
    }
};

228. 汇总区间

  • 恰好覆盖有序数组中所有数字 的 最小有序 区间范围列表
  • https://leetcode-cn.com/problems/summary-ranges/

方法二

  • ret.push_back(move(temp));注意move这个方法:
    https://blog.csdn.net/qq_42147816/article/details/104452663#t34
class Solution {
public:
    vector<string> summaryRanges(vector<int>& nums) {
        vector<string> ret;
        int i = 0;
        int n = nums.size();
        while (i < n) {
            int low = i;
            i++;
            while (i < n && nums[i] == nums[i - 1] + 1) {
                i++;
            }
            int high = i - 1;
            string temp = to_string(nums[low]);
            if (low < high) {
                temp.append("->");
                temp.append(to_string(nums[high]));
            }
             // move后值被转移,temp为空
            ret.push_back(move(temp));
        }
        return ret;

// https://leetcode-cn.com/problems/summary-ranges/solution/hui-zong-qu-jian-by-leetcode-solution-6zrs/

    }
};

268. 丢失的数字

  • 找出 [0, n] 这个范围内没有出现在数组中的那个数。线性时间复杂度、仅使用额外常数空间
  • https://leetcode-cn.com/problems/missing-number/

方法一:

排序or哈希,时复or空复高

//方法一:排序
class Solution {
public:
    int missingNumber(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int i;
        for(i=0;i<nums.size();i++){
            if(nums[i]!=i)
                break;
        }
        return i;
    }
};

//方法二:哈希法
class Solution {
public:
    int missingNumber(vector<int>& nums) {
        map<int,int> mp;
        int i;
        int n=nums.size();
        for(i=0;i<n;i++){
            mp[nums[i]]=-1;
        }

        for(i=0;i<=n;i++){
            if(mp[i]!=-1)    break;
        }
        return i;
    }
};

方法二:位运算

  • 按位**^异或运算符,按位~反**运算符
class Solution {
    // 位运算方法
   //按位^异或运算符,按位~反运算符
public:
    int missingNumber(vector<int>& nums) {
    int res = nums.size();  
    for(int i = 0; i < nums.size(); ++i)
        res = res ^ i ^ nums[i];            // a^b^b = a;
    return res ;
    }
};
// https://leetcode-cn.com/problems/missing-number/solution/c-z-by-zrita-14/

方法三:位运算

  • 数学方法:求出 [0…n]的和,减去数组中所有数的和,就得到了缺失的数字
class Solution {
    // 数学方法:求出 [0..n]的和,减去数组中所有数的和,就得到了缺失的数字
public:
    int missingNumber(vector<int>& nums) {
    int sum = 0, n = nums.size();
    for(int n : nums)
        sum += n;
    return (n * (n+1)) / 2 - sum;
    }
};
//https://leetcode-cn.com/problems/missing-number/solution/c-z-by-zrita-14/

283. 移动零

  • 将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
  • https://leetcode-cn.com/problems/move-zeroes/
  • 方法一:简单无套路
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
    int n=nums.size();
    int i=0;
    int cnt=0;
    while(i<n){
        if(nums[i]==0)
            cnt++;
        else if(nums[i]!=0)
            nums[i-cnt]=nums[i]; 
        i++;
    }
    i=i-cnt;
    while(i<n){
        nums[i]=0;
        i++;
    }
    }
};

448. 找到所有数组中消失的数字

  • 找到所有在 [1, n] 范围之间没有出现在数组中的数字。
  • https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array/

方法一

  • emplace_back还是比push_back好一点的
class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        map<int,int> mp;
        vector<int> ans;
        int n=nums.size();
        for(int i=0;i<n;i++){
            mp[nums[i]]=-1;
        }
        for(int i=1;i<=n;i++){
            if(mp[i]!=-1)
                ans.push_back(i); // 换成emplace_back后时间从228---204
        }
        return ans;
    }
};

方法二

  • C++数组声明方式注意下
  • memset方法注意下
class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        int n=nums.size();
        vector<int> ans;
        // 记住声明方式
        //int *a = new int[m];
        //memset( &a, 0, sizeof(a) ); 
        //注意第一个参数是指针类型,a不是指针变量,要加&
        //memset按字节赋值,int为4字节      
        for(int i=0;i<n;i++){
            if(nums[abs(nums[i])-1] > 0)
                nums[abs(nums[i])-1]=-nums[abs(nums[i])-1];
        }
        for(int i=0;i<n;i++){
            if(nums[i]>0)
                ans.push_back(i+1);
        }
        return ans;
    }
};

485. 最大连续1的个数

  • 二进制数组, 计算其中最大连续1的个数
  • https://leetcode-cn.com/problems/max-consecutive-ones/
  • 方法一:无套路
class Solution {
public:
    int findMaxConsecutiveOnes(vector<int>& nums) {
    int maxcnt=0;
    int cnt=0;
    int n=nums.size();
    for(int i=0;i<n;i++){
        if(nums[i]==1)  cnt++;
        else if(nums[i]==0 && cnt>maxcnt) {
            maxcnt=cnt;
            cnt=0;
        }
        else cnt=0;
    }
    // 最后一定再比较一次!
    return cnt>maxcnt?cnt:maxcnt;
    }
};

509. 斐波那契数

  • 给你 n ,请计算 F(n)
  • https://leetcode-cn.com/problems/fibonacci-number/

方法一

递归

class Solution {
public:
    int fib(int n) {
        if(n==0)    return 0;
        if(n==1)    return 1;
        else return fib(n-1) + fib(n-2);
    }
};

方法二:滚动数组

  • 由于重复计算了太多,采用滚动数组
class Solution {
public:
// 滚动数组的方法
    int fib(int n) {
        if (n < 2) {
            return n;
        }
        // 只需要保留相邻2个状态即可
        int p = 0, q = 0, r = 1;
        for (int i = 2; i <= n; ++i) {
            p = q;
            q = r;
            r = p + q;
        }
        return r;
    }
};
// https://leetcode-cn.com/problems/fibonacci-number/solution/fei-bo-na-qi-shu-by-leetcode-solution-o4ze/

561. 数组拆分 I

  • 将这些数分成 n 对, 例如 (a1, b1), (a2, b2), …, (an, bn) ,使得从 1 到 n 的 min(ai, bi) 总和最大。
  • https://leetcode-cn.com/problems/array-partition-i/
  • 方法一:排序后 i+=2 求和即可。排序使得配对产生的总损失最小化,总金额现在将达到最大值。
class Solution {
public:
    int arrayPairSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int ans=0;
        for(int i=0;i<nums.size();i+=2){
            ans+=nums[i];
        }
        return ans;
    }
};

566. 重塑矩阵

  • 实现reshape:它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据
  • https://leetcode-cn.com/problems/reshape-the-matrix/
class Solution {
public:
    vector<vector<int>> matrixReshape(vector<vector<int>>& nums, int r, int c) {
        vector<vector<int> > res(r, vector<int>(c, 0));
        int row = nums.size();
        int col = nums[0].size();
        if ( row == 0 || row * col != r * c ) return nums;

        int curRow = 0, curCol = 0;
        for ( int i = 0; i < row; ++i ) {
            for ( int j = 0; j < col; ++j ) {
                res[curRow][curCol] = nums[i][j];
                ++curCol;
                // 当前行满了, 变成下一行
                if ( curCol == c ) {
                    curCol = 0;
                    ++curRow;
                }
            }
        }
        return res;
    }
};

605. 种花问题

  • 花不能种植在相邻的地块上,flowerbed 表示花坛,由若干 0 和 1 组成,1表示种了花
  • https://leetcode-cn.com/problems/can-place-flowers/

方法二

思路清晰的跳格子法

  • 遍历到index遇到1时,说明这个位置有花,那必然从index+2的位置才有可能种花
  • index遇到0时,由于每次碰到1都是跳两格,因此前一格必定是0,此时只需要判断下一格是不是1即可得出index这一格能不能种花
class Solution {
public:
    bool canPlaceFlowers(vector<int>& flowerbed, int n) {
        int t = flowerbed.size();
        if(t==0)    return true;
        int i=0;
       while(i < t && n > 0) {
		if (flowerbed[i] == 1) {
			i += 2;
		} else if (i == t - 1 || flowerbed[i + 1] == 0) {
			n--;
			i += 2;
		} else {
			i += 3;
		}
	}
	return n <= 0;
// https://leetcode-cn.com/problems/can-place-flowers/solution/fei-chang-jian-dan-de-tiao-ge-zi-jie-fa-nhzwc/
 }
};

628. 三个数的最大乘积

  • 在数组中找出由三个数组成的最乘积,包含负数和0
  • https://leetcode-cn.com/problems/maximum-product-of-three-numbers/

方法一

sort+讨论情况做

class Solution {
public:
    int maximumProduct(vector<int>& nums) {

        int n=nums.size();
        if(n==3)    return nums[0]*nums[1]*nums[2];
        sort(nums.begin(),nums.end());
        int i=0,max;
        while(i < n && nums[i] <= 0)
            i++;
        // 全为正数
        if(i == 0)  return nums[n-1]*nums[n-2]*nums[n-3];
        // 全为负数或有0
         if(i == n)   return nums[n-1]*nums[n-2]*nums[n-3];
        // 有负数,第一个正数下标为i;
        else if(i<n){
           //1正2负 > 3正
           max = nums[n-1]*nums[0]*nums[1] > nums[n-1]*nums[n-2]*nums[n-3]? nums[n-1]*nums[0]*nums[1]: nums[n-1]*nums[n-2]*nums[n-3];

        }
         return max;
    }
};

方法二:一句话

  • sort+max一句话
  • 时复和自己的方法一样,空复小。

class Solution {
public:
    int maximumProduct(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int n = nums.size();
        return max(nums[0] * nums[1] * nums[n - 1], nums[n - 3] * nums[n - 2] * nums[n - 1]);
    }
};
// https://leetcode-cn.com/problems/maximum-product-of-three-numbers/solution/san-ge-shu-de-zui-da-cheng-ji-by-leetcod-t9sb/

方法三:归纳情况

  • 我们实际上只要求出数组中最大的三个数以及最小的两个数,因此我们可以不用排序,用线性扫描直接得出这五个数。
  • 时复最小,空复一般
class Solution {
public:
    int maximumProduct(vector<int>& nums) {
        // 最小的和第二小的
        int min1 = INT_MAX, min2 = INT_MAX;
        // 最大的、第二大的和第三大的
        int max1 = INT_MIN, max2 = INT_MIN, max3 = INT_MIN;

        for (int x: nums) {
            if (x < min1) {
                min2 = min1;
                min1 = x;
            } else if (x < min2) 
                min2 = x;
           
            if (x > max1) {
                max3 = max2;
                max2 = max1;
                max1 = x;
            } else if (x > max2) {
                max3 = max2;
                max2 = x;
            } else if (x > max3)
                max3 = x;       
        }
        return max(min1 * min2 * max1, max1 * max2 * max3);
    }
};
// https://leetcode-cn.com/problems/maximum-product-of-three-numbers/solution/san-ge-shu-de-zui-da-cheng-ji-by-leetcod-t9sb/

643. 子数组最大平均数 I

  • 找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数。
  • https://leetcode-cn.com/problems/maximum-average-subarray-i/

方法二:滑动窗口

大小为k的滑动窗口:窗口向前滑动时,每向前滑动一位,就减去上一个子数组的首元素,加上新加进来子数组的新元素

class Solution {
public:
    double findMaxAverage(vector<int>& nums, int k) {

	double sum_k = 0;
	for (int i = 0; i < k; i++)
		sum_k += nums[i];
	double max_sum_k = sum_k;
	for (int i = k; i < nums.size(); i++) {
		sum_k = sum_k - nums[i - k] + nums[i];
		max_sum_k = max(max_sum_k, sum_k);
	}
	return max_sum_k / k;
}
// https://leetcode-cn.com/problems/maximum-average-subarray-i/solution/chua-dong-chuang-kou-jie-jue-lian-xu-zi-shu-zu-wen/
};

665. 非递减数列

  • 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列。

  • https://leetcode-cn.com/problems/non-decreasing-array/

  • 方法一:
    就暴力···试错了好多用例,最后结果不错。时复99.8%

class Solution {
public:
    bool checkPossibility(vector<int>& nums) {
        int i=0,j=1,n,k;
        n = nums.size();
        while(j < n && nums[i] <= nums[j]){
            i++; j++;
        }
        // 本身是非递减的,或者最后一个元素递减了(此时当然可以修改)
        if(j >= n-1) return true;
        // 只有第一个元素不符合的话也OK
        for(k=1;k<n-1 && nums[k] <= nums[k+1];k++);
        if(k >= n-1)   return true;

        // 普通情况:
        // 出现一个元素nums[i]使得nums[i] > nums[j]
        // 判断它后面的是不是都是非递减
        i = j+1; j = j+2;
        
        // 先判断i的左右元素是否有非递减关系
        // nums[i-1]或nums[i-2]如果有一个有问题
        // 便不可能成为阶梯式的数组
        if(i >= 2 && nums[i-2] <= nums[i]){
            //  再判断i后面的是不是非递减
            while(j < n && nums[i] <= nums[j]){
                i++; j++;
            }
            if(j>=n) return true;
        }
        else if(i >=3 && nums[i-3] <= nums[i-1]){
            i=i-1;j=j-1;
            while(j < n && nums[i] <= nums[j]){
                i++; j++;
            }
            if(j>=n) return true;
        }
        return false;
    }
};

674. 最长连续递增序列

  • 找到最长且 连续递增的子序列,并返回该序列的长度。
  • https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence/
  • 方法一:没啥难度,贪心
class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        int Max=1;
        int n=nums.size();
        if(n == 0)  return 0;
        for(int i=1;i<n;i++){
            int len=1;
            while(i < n && nums[i-1] < nums[i]){
                len++;
                i++;
            }
            // Max = Max
            if(Max < len)   Max = len;
        }
        return Max;
    }
};

697. 数组的度

  • 与 nums 拥有相同大小的度的最短连续子数组,返回其长度。度的定义是指数组里任一元素出现频数的最大值
  • https://leetcode-cn.com/problems/degree-of-an-array/
  • 方法一:无技巧,计频,然后遍历频次为度的找最短连续子数组。要设置vis不然会超时。
class Solution {
public:
    int findShortestSubArray(vector<int>& nums) {
        map<int ,int> mp;
        map<int ,int> vis;
        int n=nums.size();
        int cnt=0;
        int i,ans=n;
        for(i=0; i < n; i++){
            mp[nums[i]]++;
            if(mp[nums[i]] > cnt) 
                cnt= mp[nums[i]];           
        }
        for(i=0; i < n; i++){
            if(mp[nums[i]] == cnt && !vis[nums[i]]){
                vis[nums[i]] = 1;
                int temp = 1;
                int j = i + 1;
                while(j < n && temp < cnt) {
                    if(nums[j] == nums[i])
                        temp++; // 子序列中出现的频数
                    j++;
                }        
                if(temp == cnt && (j-i) < ans)
                    ans = j-i;                
            }               
        }
        return ans;
    }
};

717. 1比特与2比特字符

  • 第一种字符可以用一比特0来表示。第二种字符可以用两比特(10 或 11)来表示。若字符串的总是由0结束,问最后一个字符是否必定为一个一比特字符。
  • https://leetcode-cn.com/problems/1-bit-and-2-bit-characters/

方法二:

无技巧,想明白了怎么监测的就行

class Solution {
public:
    bool isOneBitCharacter(vector<int>& bits) {
        int n=bits.size();
        // if(n > 1 && bits[n-2] == 0) return true;
        int i=0;
        while(i < n - 1){
            if(bits[i] == 0)
                i+=1;
            else 
                i+=2;
        }
        //退出的时候看最后跳的步长是1还是2:
        //i==bits.length-1 说明最后跳的步长是1,说明是1bit 0结尾
        //i==bits.length 说明最后跳的步长是2,说明不是1bit 0 结尾
        return i == n-1;
    }
};

724. 寻找数组的中心索引

  • 中心索引 是数组的一个索引,其左侧所有元素相加的和等于右侧所有元素相加的和。
  • https://leetcode-cn.com/problems/find-pivot-index/

方法一:

  • 毫无用处的dp
class Solution {
public:
    int pivotIndex(vector<int>& nums) {

    int dpl[10000];
    int dpr[10000];
    int n = nums.size();
    dpl[0] = 0;
    dpr[n-1] = 0;
    for(int i = 1; i < n; i++){
        dpl[i] = dpl[i-1] + nums[i-1];
        dpr[n-i-1] = dpr[n-i] +nums[n-i];
    }

    for(int i=0; i < n;i++){
        if(dpl[i] == dpr[i])
            return i;
    }
    return -1;
    }
};

方法二

  • 左 = 右的话,直接求出这一行的和total,左+右+元素本身=total
class Solution {
public:
    int pivotIndex(vector<int> &nums) {
        //int total = accumulate(nums.begin(), nums.end(), 0);
        int sum = 0;
        int total= 0;
        for (int i = 0; i < nums.size(); ++i){
            total+=nums[i];
        }
        for (int i = 0; i < nums.size(); ++i) {
            if (2 * sum + nums[i] == total) {
                return i;
            }
            sum += nums[i];
        }
        return -1;
    }
};

// https://leetcode-cn.com/problems/find-pivot-index/solution/xun-zhao-shu-zu-de-zhong-xin-suo-yin-by-gzjle/

747. 至少是其他数字两倍的最大数

  • 最大元素是否至少是数组中每个其他数字的两倍
  • https://leetcode-cn.com/problems/largest-number-at-least-twice-of-others/
  • 方法一:z只用比较是不是次大数的2倍
class Solution {
public:
    int dominantIndex(vector<int>& nums) {

        int pos=0;
        if(nums.size() == 1)    return pos;
        int max=nums[0],temp=-1;
        for(int i=0; i < nums.size(); i++){
            if(nums[i] <= temp || nums[i] == max)  
                continue;
            else if(nums[i] > max) {
                temp = max;
                max = nums[i]; 
                pos = i;
            } 
            else 
                temp = nums[i];                        
        }
        if(temp && (max / temp) >= 2 || temp == 0) 
            return pos;
        else return -1;
    }
};

766. 托普利茨矩阵

  • 矩阵上每一条由左上到右下的对角线上的元素都相同,那么这个矩阵是 托普利茨矩阵
  • https://leetcode-cn.com/problems/toeplitz-matrix/

方法二

伤害极强,只需要和它zuo的元素比较久可以了

class Solution {
public:
        bool isToeplitzMatrix(vector<vector<int>>& matrix) {
        if(matrix.size()==1 || matrix[0].size()==1) return true;
        for(int i=1; i<matrix.size(); i++){
            for(int j=1; j<matrix[0].size(); j++){
                if(matrix[i][j]!=matrix[i-1][j-1]) return false;
            }
        }
        return true;
    }
// https://leetcode-cn.com/problems/toeplitz-matrix/solution/c-jian-dan-ti-jie-by-shi-fen-fang-qi-zhong-5/
};

830. 较大分组的位置

  • 字符串 s 中,包含由一些连续的相同字符所构成的分组。所有包含大于或等于三个连续字符的分组为 较大分组
  • https://leetcode-cn.com/problems/positions-of-large-groups/
  • 方法一:无套路
class Solution {
public:
    vector<vector<int>> largeGroupPositions(string s) {

        int n=s.length();
        vector<vector<int>> ans;
        for(int i=0; i<n; i++){
            char c = s[i];
            int j = i;
            while(j+1 < n && c == s[j+1]){
                j++;
                c = s[j];
            }
            if(j-i > 1){
                vector<int> temp;
                temp.push_back(i);
                temp.push_back(j);
                ans.push_back(move(temp));
            }
            i = j;
        }
        return ans;
    }
};

832. 翻转图像

  • 先水平翻转图像,然后反转图像并返回结果。
  • https://leetcode-cn.com/problems/flipping-an-image/
  • 方法一:无难度
class Solution {
public:
    vector<vector<int>> flipAndInvertImage(vector<vector<int>>& A) {
        int n = A.size();
        for(int j = 0; j < n; j++ ){
            for(int i = 0; i < (n+1)/2; i++){
                int temp = A[j][n-1-i] ^ 1;
                A[j][n-1-i] = A[j][i] ^ 1;
                A[j][i] = temp;
            }
        }
        return A;
    }
};

867. 转置矩阵

  • just转置
  • https://leetcode-cn.com/problems/transpose-matrix/
  • 方法一:大力出奇迹,结果还不错。
class Solution {
public:
    vector > transpose(vector>& A) {
        vector > v(A[0].size(),vector(A.size(),0));
        for(int i=0;i

888. 公平的糖果棒交换

  • 交换后,他们有相同的糖果总量。一个人拥有的糖果总量是他们拥有的糖果棒大小的总和。返回一个整数数组 ans,其中 ans[0] 是爱丽丝必须交换的糖果棒的大小,ans[1] 是 Bob 必须交换的糖果棒的大小。
  • https://leetcode-cn.com/problems/fair-candy-swap

方法二

class Solution {
public:
    vector<int> fairCandySwap(vector<int>& A, vector<int>& B) {
        int sumA = accumulate(A.begin(), A.end(), 0);
        int sumB = accumulate(B.begin(), B.end(), 0);
        int delta = (sumA - sumB) / 2;
        unordered_set<int> rec(A.begin(), A.end());
        vector<int> ans;
        for (auto& y : B) {
            int x = y + delta;
            if (rec.count(x)) {
                ans = vector<int>{x, y};
                break;
            }
        }
        return ans;
    }
};
// https://leetcode-cn.com/problems/fair-candy-swap/solution/gong-ping-de-tang-guo-jiao-huan-by-leetc-tlam/

905. 按奇偶排序数组

  • 非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后跟着所有奇数元素。
  • https://leetcode-cn.com/problems/sort-array-by-parity/
  • 方法一:无难度
class Solution {
public:
    vector<int> sortArrayByParity(vector<int>& A) {
        int i=0,j=0;
        int n = A.size();
        // i指向偶
        while(i < n && A[i] % 2 != 0)
            i++;
        // j指向奇
        while(j < n && A[j] % 2 == 0)
            j++;
        // 全奇或全偶
        if(i == n || j == n)    return A;

        while(i < n && j < n){
            // 偶在奇后面
            if(i > j){
                swap(A[i],A[j]);
                // 移动i
                i++;
                while(i < n && A[i] % 2 != 0)
                    i++;
                // 移动j
                j++;
                while(j < n && A[j] % 2 == 0)
                    j++;
            }
            // 奇在偶后面
            else {
                // 只移动i
                i++;
                while(i < n && A[i] % 2 != 0)
                    i++;
            }            
        }
        return A;
    }
};

914. 卡牌分组

  • 每张牌上都写着一个整数。选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组:每组都有 X 张牌;组内所有的牌上都写着相同的整数。
    仅当你可选的 X >= 2 时返回 true。
  • https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards

方法二:

  • 认清问题本质:无非是先计数cnt,然后求GCD
  • 求gcd的函数记得头文件#include< algorithm>
class Solution {
    // 可以添加在这里
    int cnt[10000];
public:
    bool hasGroupsSizeX(vector<int>& deck) {
        for (auto x: deck) 
            cnt[x]++;
        int g = cnt[0];
         // gcd:#include< algorithm>
        for (int i = 1; i < 10000; ++i) {
            if (cnt[i]) {
                 g = gcd(g, cnt[i]);     
            }
        }
        return g >= 2;
    }
};
// https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards/solution/qia-pai-fen-zu-by-leetcode-solution/   

922. 按奇偶排序数组 II

  • 重新排列,使得当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。
  • https://leetcode-cn.com/problems/sort-array-by-parity-ii/
  • 方法一:无技巧
class Solution {
public:
    vector<int> sortArrayByParityII(vector<int>& A) {
        int i=1,j=0;
        int n = A.size();
        //i偶j奇
        while(i < n && j < n){
             // 搜寻在奇数位置上的偶数
            while(i < n && A[i]%2 != 0  ){
                i+=2;
            }
            // 搜寻在偶数位置上的奇数
            while(j < n && A[j]%2 == 0 ){
                j+=2;
            }
            if(i < n && j < n)
                swap(A[i],A[j]);
        }
        return A;
    }
};

941. 有效的山脉数组

  • 先严格递增,再严格递减的数组
  • https://leetcode-cn.com/problems/valid-mountain-array/
  • 方法一:无套路
class Solution {
public:
    bool validMountainArray(vector<int>& arr) {
        int n = arr.size();
        int i = 0;
        // 退出for时是山顶
        while(i < n-1 && arr[i] < arr[i+1]){
            i++;
        }
        if(i == n-1 || i == 0)  return false;
        i++;
        while(i < n && arr[i-1] > arr[i])
            i++;
        if(i < n)
            return false;
        return true;
    }
};

985. 查询后的偶数和

  • 题意复杂,实际上简单,不再赘述
  • https://leetcode-cn.com/problems/sum-of-even-numbers-after-queries/
  • 方法一:
class Solution {
public:
    vector<int> sumEvenAfterQueries(vector<int>& A, vector<vector<int>>& queries) {
        vector<int> answer;
        int sum = 0;
        // 先求偶数和
        for(int i = 0; i < A.size(); i++)
            if(A[i]%2 == 0) 
                sum += A[i];
        for(int i = 0; i < queries.size(); i++){
            int val = queries[i][0];
            int index = queries[i][1];
            int temp = A[index];
            A[index] += val;    
            // 如果改变的数是偶数
            if(temp%2 == 0)
                sum -= temp;
            // 如果改变后的数是偶数
            if(A[index]%2 == 0)
                sum += A[index];
            answer.emplace_back(sum);
        }
        return answer;
    }
};

989. 数组形式的整数加法

  • X用数组表示,K只是一个整数,相加后的结果用数组表示
  • https://leetcode-cn.com/problems/add-to-array-form-of-integer/

方法二

  • 简单直接的方法
class Solution {
public:
    // 简单直接的方法
    vector<int> addToArrayForm(vector<int>& A, int K) {
        // 注意一下反转A,或者从A.size()-1开始才是个位
        reverse(A.begin(), A.end());
        int c = 0;
        for (int i = 0; (K != 0 || c != 0); i++) {
            // 这种为A添加0的方法比讨论A和K的长度要好
            if (i >= A.size()) {
                A.push_back(0);
            }

            // 取A的末尾数字
            int a = A[i];
            // 取K的末尾数字
            int b = K % 10;
            // K移位
            K /= 10;

            int sum = a + b + c;
            // 更新A[i]
            A[i] = (sum % 10);
            // 更新进位
            c = sum / 10;
        }

        reverse(A.begin(), A.end());
        return A;
    }
};
// https://leetcode-cn.com/problems/add-to-array-form-of-integer/solution/add-to-array-by-ikaruga-tnbr/

方法三

  • 稍微复杂的方法
class Solution {
public:
    // 一个稍微复杂的方法
    vector<int> addToArrayForm(vector<int>& A, int K) {
        int i = A.size()-1;
        // 直接把K加到A中,再取个位数
        while(K > 0){
            // A[i]+K,与实际上A[i]只保留个位数
            A[i] += K;
            // 此时K实际上是:进位的值 + K
            K = A[i] / 10;
            // A[i]只保留个位数
            A[i--] %= 10;

            // K长A短的情况
            if(i < 0 && K > 0){
                // 在开头插入0
                A.insert(A.begin(),0);
                // i指针放在开头
                i = 0;
            }
        }
        return A;
    }
};
// https://leetcode-cn.com/problems/add-to-array-form-of-integer/solution/pythonc-san-chong-jie-fa-by-milomusiala-7wc5/

999. 可以被一步捕获的棋子数

  • 下棋,题意复杂,实现简单

  • https://leetcode-cn.com/problems/available-captures-for-rook/

  • 方法一:直接暴力

    class Solution {
    public:
        int numRookCaptures(vector>& board) {
            int r = board.size();
            int c = board[0].size();
            int ri,rj;
            int cnt = 0;
            // 找车
            for(int i = 0; i < r; i++)
                for(int j = 0; j < c; j++)
                    if(board[i][j] == 'R'){
                        ri = i;
                        rj = j;
                        break;
                    }                    
            //车向4个方向移动,判断停止条件
            // 向东
            for(int i = ri; i < r; i++)
            {
                if(board[i][rj] == 'B' )
                    break;
                if(board[i][rj] == 'p'){
                    cnt++;
                    break;
                }
                    
            }
            // 向西
            for(int i = ri; i >= 0; i--)
            {
                if(board[i][rj] == 'B' )
                    break;
                if(board[i][rj] == 'p'){
                    cnt++;
                    break;
                }
            }
            // 向北
            for(int j = rj; j >= 0; j--)
            {
                if(board[ri][j] == 'B' )
                    break;
                if(board[ri][j] == 'p'){
                    cnt++;
                    break;
                }
            }
             // 向南
            for(int j = rj; j < r; j++)
            {
                if(board[ri][j] == 'B' )
                    break;
                if(board[ri][j] == 'p'){
                    cnt++;
                    break;
                }
            }
            return cnt;
        }
    };
    
  • 1002. 查找常用字符

  • 返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表

  • https://leetcode-cn.com/problems/find-common-characters/

    方法二

    class Solution {
    public:
        vector commonChars(vector& A) {
            vector result;
            if (A.size() == 0) return result;
            int hash[26] = {0}; // 用来统计所有字符串里字符出现的最小频率
            for (int i = 0; i < A[0].size(); i++) { // 用第一个字符串给hash初始化
                // 注意字符到int转换的写法
                hash[A[0][i] - 'a']++;
            }
    
            int hashOtherStr[26] = {0}; // 统计除第一个字符串外字符的出现频率
            // 关键
            for (int i = 1; i < A.size(); i++) {
                memset(hashOtherStr, 0, 26 * sizeof(int));
                for (int j = 0; j < A[i].size(); j++) {
                    hashOtherStr[A[i][j] - 'a']++;
                }
                // 更新hash,保证hash里统计26个字符在所有字符串里出现的最小次数
                for (int k = 0; k < 26; k++) { 
                    hash[k] = min(hash[k], hashOtherStr[k]);
                }
            }
            // 将hash统计的字符次数,转成输出形式
            for (int i = 0; i < 26; i++) {
                while (hash[i] != 0) { // 注意这里是while,多个重复的字符
                    string s(1, i + 'a'); // char -> string
                    result.push_back(s);
                    hash[i]--;
                }
            }
    
            return result;
        }
    };
    // https://leetcode-cn.com/problems/find-common-characters/solution/1002-cha-zhao-chang-yong-zi-fu-ha-xi-fa-jing-dian-/
    

1013. 将数组分成和相等的三个部分

  • 给你一个整数数组 A,只有可以将其划分为三个和相等的非空部分时才返回 true,否则返回 false

  • https://leetcode-cn.com/problems/partition-array-into-three-parts-with-equal-sum/

方法一:包含加速代码

思路简单,找3次sum/3的和即可

// c++提速https://blog.csdn.net/weixin_43213056/article/details/100548067
static const auto _ = []()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    return nullptr;
}();
class Solution {

public:

    bool canThreePartsEqualSum(vector& arr) {
        int n = arr.size();
        int i=1,j = n-2;
        int sum = accumulate(arr.begin() , arr.end() , 0);
        int sum1 = 0;
        // 如果sum不能恰好分成3份
        if(sum%3 != 0)
            return false;

        // 从前往后找sum/3
        sum1 = arr[0];
        while(i < n  && sum1 != sum/3){
            sum1 += arr[i];
            i++;
        }
        if(i == n ) return false;

        // 从后往前找sum/3
        sum1 = arr[n-1];
        while(j > i && sum1 != sum/3 ){
            sum1 += arr[j];
            j--;
        }
        if(i-1 == j)   return false;
        // 从i到j求sum1,与sum/3比较
        sum1 = 0;
        while(i <= j){
            sum1 += arr[i];
            i++;
        }
        if(sum1 == sum/3)   return true;
        else return false;
    }
};

1018. 可被 5 整除的二进制前缀

  • 我们定义 N_i:从 A[0]A[i] 的第 i 个子数组被解释为一个二进制数(从最高有效位到最低有效位)。
  • https://leetcode-cn.com/problems/binary-prefix-divisible-by-5/)
  • 输入:[0,1,1] 输出:[true,false,false]
    解释:输入数字为 0, 01, 011;也就是十进制中的 0, 1, 3 。只有第一个数可以被 5 整除,因此 answer[0] 为真。

方法一:

一开始是溢出,后来倒数第二个用例超时,无解

class Solution {
public:
    vector prefixesDivBy5(vector& A) {
        vector answer;
        int n = A.size();
        vector tmp;
        
        for(int i = 0; i < n; i++){ 
            int N_i = 0;          
            // 确定第1位的值
            if(A[i] == 1)   tmp.emplace_back(1);
            else tmp.emplace_back(0);  
            // 加到N_i上
            N_i += tmp[i];
            // 从第2位开始*2遍历          
            for(int j = i-1; j >= 0; j--){
                tmp[j] = tmp[j]*2;
                // 改进了,只取个位数。
                tmp[j] %= 10;
                N_i += tmp[j];
            }
            if(N_i%5 == 0) answer.emplace_back(true);
            else answer.emplace_back(false);
        }
        return answer;
    }
};

方法二:左移一位+只保留余数

  • c++的左移右移运算符都是二进制下的左移右移,2倍而不是10倍的关系。与此题思路不谋而合
  • 只保留余数可以避免overflow
class Solution {
public:
    vector prefixesDivBy5(vector& A) {
        vector ans(A.size());
        int num = 0;
        for(int i = 0 ; i < A.size(); i ++){
            // 左移一位,乘2,再加上新的末位
            num = (num<<1) + A[i];
            // 只保留最后一位,但实际上直接num %= 5也是可以的
            // num %= 10;
            // ans[i] = (num % 5 == 0);
            num %= 5;
            ans[i] = (num == 0);         
        }
        return ans;
    }
};
// https://leetcode-cn.com/problems/binary-prefix-divisible-by-5/solution/ji-bai-shuang-100zui-rong-yi-li-jie-de-s-0dba/

1051. 高度检查器

  • 返回能让所有学生以 非递减 高度排列的最小必要移动人数(不是移动次数)。

  • https://leetcode-cn.com/problems/height-checker/

  • 方法二:

    关键不要想复杂····将输入的参数赋值给另外一个vector容器, 然后将该容器内的元素进行排序, 最后同heights进行对比, 统计在相同位上的数值不相同的元素个数总和.

class Solution {
public:
// 将输入的参数赋值给另外一个vector容器, 然后将该容器内的元素进行排序, 最后同heights进行对比, 统计在相同位上的数值不相同的元素个数总和.
    int heightChecker(vector& heights) {
        int size = heights.size();
        vector vec(heights);
        sort(vec.begin(), vec.end());
        int i = 0;
        int j = 0;
        int count = 0;
        for(i = 0, j = 0; i < size, j < size; i++, j++)
        {
            if(heights[i] != vec[j])
            {
                ++count;
            }
        }
        return count;
    }
};
// https://leetcode-cn.com/problems/height-checker/solution/fen-xiang-jie-ti-si-lu-by-wilson1116/

1089. 复写零

  • 将数组中出现的每个零都复写一遍,并将其余的元素向右平移。请不要在超过该数组长度的位置写入元素。

    就地进行上述修改

方法一:迭代器在insert里的失败运用

方法一失败是因为迭代器失效

https://www.cnblogs.com/fnlingnzb-learner/p/9300073.html

对于序列式容器,比如vector,删除或添加当前的iterator会使后面所有元素的iterator都失效。这是因为顺序容器内存是连续分配(分配一个数组作为内存)。

当删除一个元素后,其他数据的地址发生了变化,之前获取的迭代器根据原有的信息就访问不到正确的数据

插入时,因为size()==capacity(),故插入元素后,vector被重新分配内存。可以看下面两个

https://www.jianshu.com/p/6f08b1d4271a

https://www.zhihu.com/question/37352989

解决方法一:

获取insert或者erase返回的迭代器,以便用重新获取新的有效的迭代器进行正确的操作:

	iter=vec.insert(iter);   
 	iter=vec.erase(iter); 
解决方法二:

在添加、删除、修改元素时,尽量直接使用begin()和end(),或者使用insert()和erase()更新相应的迭代器,避免使用迭代器的中间量。

vector vi;
//i保存的是vi的迭代器,有时操作后(如添加元素,删除元素)不确定i是否有效
auto i=vi.begin()+n;
vi.erase(i);
//尽量直接使用begin()和end(),避免使用中间量i
vi.erase(vi.begin()+n);
//下面的表达式更好,因为它会自动更新i
i=vi.erase(i);

方法一代码不贴了

方法二

两次遍历,提前预留空间

class Solution {
public:
// 两次遍历,提前预留空间
    void duplicateZeros(vector& arr) {
        int len = arr.size();
        int i = 0, count = 0;
        /*第一次遍历,计算有效位置i,统计能装下的有效数据个数i + count*/
        for(;i < len; i++) {
            if (arr[i] == 0) count++;
            if ((i + count) >= len - 1) break;
        }

        /*特殊判断,能装下的有效数据个数为i + count*/
        if ((count + i) > len - 1) {
            arr[len-- - 1] = arr[i--];
        }

        /*从i开始倒着填充数据*/
        int j = len - 1;
        while (j > i) {
            if (arr[i] == 0) {
                arr[j] = 0;
                arr[--j] = 0;
            } else {
                arr[j] = arr[i];
            }

            i--;
            j--;
        }
    }
};
// https://leetcode-cn.com/problems/duplicate-zeros/solution/fu-xie-ling-bao-li-guan-fang-shuang-zhi-zhen-by-hu/

1122. 数组的相对排序

  • arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾。
  • https://leetcode-cn.com/problems/relative-sort-array/

方法二:计数排序

  • frequency记录每一个元素在arr1中出现的次数,再去arr2中比对,该输出某个数几次,然后frequency置0。
  • 空间节省技巧:找出数组 arr1中的最大值upper,使用长度为upper+1的数组
class Solution {
public:
    // 计数排序
    vector relativeSortArray(vector& arr1, vector& arr2) {
        // 找出数组 arr1中的最大值upper,使用长度为upper+1的数组
        int upper = *max_element(arr1.begin(), arr1.end());
        // frequency记录每一个元素在arr1中出现的次数
        vector frequency(upper + 1);
        for (int x: arr1) {
            ++frequency[x];
        }
        vector ans;
        // 我们将 frequency[x]个数值加入答案中,并将 frequency[x]清零。
        for (int x: arr2) {     
            for (int i = 0; i < frequency[x]; ++i) {
                ans.emplace_back(x);
            }
            frequency[x] = 0;
        }
        // 从0开始递增直到upper
        for (int x = 0; x <= upper; ++x) {
            // 有几次输出几遍
            for (int i = 0; i < frequency[x]; ++i) {
                ans.emplace_back(x);
            }
        }
        return ans;
    }
};
// https://leetcode-cn.com/problems/relative-sort-array/solution/shu-zu-de-xiang-dui-pai-xu-by-leetcode-solution/

1128. 等价多米诺骨牌对的数量

  • 如果其中某一张多米诺骨牌可以通过旋转 0 度或 180 度得到另一张多米诺骨牌,我们就认为这两张牌是等价的。
  • https://leetcode-cn.com/problems/number-of-equivalent-domino-pairs/

方法二:计数排序

调整顺序并将每一个二元对拼接成一个两位的正整数val

class Solution {
public:
    // 计数排序
    int numEquivDominoPairs(vector>& dominoes) {
        vector num(100);
        int ret = 0;
        for (auto& it : dominoes) {
            //调整顺序并将每一个二元对拼接成一个两位的正整数val
            int val = it[0] < it[1] ? it[0] * 10 + it[1] : it[1] * 10 + it[0];
            // 计数,第一次是0
            ret += num[val];
            num[val]++;
        }
        return ret;
    }
};
// ttps://leetcode-cn.com/problems/number-of-equivalent-domino-pairs/solution/deng-jie-duo-mi-nuo-gu-pai-dui-de-shu-li-yjlz/

1160. 拼写单词

  • 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。
  • https://leetcode-cn.com/problems/find-words-that-can-be-formed-by-characters/
  • 方法一太笨了不展示

方法二:char和int转换

  • 能用int数组就尽量不要用hash!!!

  • char和int转换:

    cnt[(int)(cc - 'a')] += 1;
    
  • count函数:统计 26 个字母出现的次数,可以复用

class Solution {
public:
// 能用int数组就尽量不要用hash!!!!
// char和int转换:cnt[(int)(cc - 'a')] += 1;
    int countCharacters(vector& words, string chars) {
    vector chars_count = count(chars); // 统计字母表的字母出现次数
    int res = 0;
    for (string& word : words) {
        vector word_count = count(word); // 统计单词的字母出现次数
        if (contains(chars_count, word_count)) {
            res += word.length();
        }
    }
    return res;
}

// 检查字母表的字母出现次数是否覆盖单词的字母出现次数
bool contains(vector& chars_count, vector& word_count) {
    for (int i = 0; i < 26; i++) {
        if (chars_count[i] < word_count[i]) {
            return false;
        }
    }
    return true;
}

// count函数:统计 26 个字母出现的次数
vector count(string& word) {
    vector counter(26, 0);
    for (char c : word) {
        counter[c-'a']++;
    }
    return counter;
}
};
// https://leetcode-cn.com/problems/find-words-that-can-be-formed-by-characters/solution/tong-ji-zi-mu-chu-xian-de-ci-shu-shu-zu-ji-qiao-cj/

你可能感兴趣的:(C/C++,#,LeetCode,leetcode,数组)