Day2- 数组part02

一、有序数组的平方

思想:

双指针:采用头尾指针,利用最大值一定是数组最左端或者最右端的思想

题目一:977. 有序数组的平方

977. 有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

/*
 * @lc app=leetcode.cn id=977 lang=cpp
 *
 * [977] 有序数组的平方
 */

// @lc code=start
class Solution {
public:
    vector sortedSquares(vector& nums) {
        int i = 0;
        int j = nums.size() - 1;
        int k = nums.size() - 1;
        vector result(nums.size(), 0);
        while (i <= j) {
            long long left = nums[i] * nums[i];
            long long right = nums[j] * nums[j];
            if (left < right) {
                result[k--] = right;
                j--;
            } else {
                result[k--] = left;
                i++;
            }
        }
        return result;
    }
};
// @lc code=end

二、长度最小的子数组

思想:

滑动窗口:本质上也是一种双指针思想,用于寻找符合条件的一个区间

 题目一:209. 长度最小的子数组

209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

/*
 * @lc app=leetcode.cn id=209 lang=cpp
 *
 * [209] 长度最小的子数组
 */

// @lc code=start
class Solution {
public:
    int minSubArrayLen(int target, vector& nums) {
        int j = 0;
        int sum = 0;
        int result = nums.size() + 1;
        for (int i = 0; i < nums.size(); i++) {
            sum += nums[i];
            while (sum >= target) {
                int len = i - j + 1;
                result = len < result? len: result;
                sum -= nums[j++];
            }
        }
        return result == nums.size() + 1? 0: result;
    }
};
// @lc code=end

题目二:904. 水果成篮

904. 水果成篮

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

  • 你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
  • 你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
  • 一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。

给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

自己写的思想:

  • 两种水果篮子类型一样时:
    • 新采摘的水果,和篮子水果类型不一样时,记录新的水果类型
    • 数量++
  • 两种水果篮子类型不一样时:
    • 新采摘水果和前一个篮子水果类型一样
      • 数量++
    • 新采摘水果和前一个篮子水果类型不一样
      • 新采摘水果和两种水果篮子之一一样时
        • 记录采摘水果的位置k,数量++
      • 新采摘水果和两种水果篮子不一样时
        • 重新利用下标位置k计算两个篮子之间的数量
        • 记录采摘水果的位置k
        • 重新标记水果篮子的种类

初始化:

位置都标记在0位置,数量为1;

特殊情况:

水果为[],直接返回0;

/*
 * @lc app=leetcode.cn id=904 lang=cpp
 *
 * [904] 水果成篮
 */

// @lc code=start
class Solution {
public:
    int totalFruit(vector& fruits) {
        int i = 0;
        int j = 0;
        int k = 0;
        int res = 0;
        int sum = 1;
        int first = fruits[i];
        int second = fruits[j];
        for (int i = 1; i < fruits.size(); i++) {
            if (first == second) {
                if (fruits[i] != first) {
                    k = i; 
                    first = fruits[i];
                }
                sum++;
            }
            else {
                if (fruits[i] == fruits[i-1])
                    sum++;
                else {
                    if(fruits[i] == second || fruits[i] == first) {
                        k = i;
                        sum++;
                    } 
                    if(fruits[i] != second && fruits[i] != first){
                        j = k;
                        res = res < sum? sum: res;
                        sum = i - j + 1;
                        k = i;
                        second = fruits[j];
                        first = fruits[i];
                    }
                }
            }
        }
        res = res < sum? sum: res;
        return res;
    }
};
// @lc code=end

Day2- 数组part02_第1张图片

虽然通过了,写的太麻烦了,看看答案 

答案借助了一个哈希表:

  • 哈希表数量小于等于2

        移动right

  • 哈希表数量大于2

        不断移动left,减少哈希表值,直到某个键值为0,移除此键值对

map常见函数

find()函数:返回一个迭代器指向键值为key的元素it,没找到返回指向map尾部的迭代器erase(it)函数it为需要删除的元素的迭代器

map可以使用it->first来访问键,it->second来访问值

/*
 * @lc app=leetcode.cn id=904 lang=cpp
 *
 * [904] 水果成篮
 */

// @lc code=start
class Solution {
public:
    int totalFruit(vector& fruits) {
        unordered_map cnt;
        int result = 0;
        int sum = 0;
        int j =0;
        for (int i = 0; i < fruits.size(); i++) {
            cnt[fruits[i]]++;
            while (cnt.size() > 2) {
                auto it = cnt.find(fruits[j]);
                it->second--;
                if (it->second == 0)
                    cnt.erase(it);
                j++;
            }
            result = max(result, i - j + 1);
        }
        return result;

    }
};

// @lc code=end

 题目三:76. 最小覆盖子串

76. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

自己写的思路:

        右指针不断移动

        当t中所有字符在哈希表中都只有一次,记录子串长度,比较

        当t中存在字符在哈希表中超过一次,移动左指针,直到没有这个字符只有一次

答案思路:

        右指针不断移动,直到覆盖所有字符

        左指针移动,记录子串长度,比较,直到超出必要字符

        重复

/*
 * @lc app=leetcode.cn id=76 lang=cpp
 *
 * [76] 最小覆盖子串
 */

// @lc code=start
class Solution {
public:
    unordered_map cnt, ori;
    bool check() {
        for (auto o: ori){
            if (cnt[o.first] < o.second)
                return false;
        }
        return true;
    }
    string minWindow(string s, string t) {
        
        for (char c: t) {
            ori[c]++;
        }
        int j = 0;
        int len = s.size() + 1;
        int ansL = -1;
        for (int i = 0;i < s.size(); i++) {
            if (ori.find(s[i]) != ori.end())
                cnt[s[i]]++;
            while (check() && (j <= i)) {
                if ((i - j + 1) < len) {
                    len = (i - j + 1);
                    ansL = j;
                }
                if (ori.find(s[j]) != ori.end())
                    cnt[s[j]]--;
                j++;
            }
        }
        return ansL == -1? "": s.substr(ansL,len);
    }
};
// @lc code=end

三、螺旋矩阵

题目一:59. 螺旋矩阵||

59. 螺旋矩阵 II

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 

思考:

循环次数:n/2

从左到右:

从上到下:

从右到左:

从下到上:

考虑整数奇偶

/*
 * @lc app=leetcode.cn id=59 lang=cpp
 *
 * [59] 螺旋矩阵 II
 */

// @lc code=start
class Solution {
public:
    vector> generateMatrix(int n) {
        int startx = 0;
        int starty = 0;
        int loop = n / 2;
        int mid = n / 2;
        int offset = 1;
        int count = 1;
        vector> num(n, vector(n, 0));
        int i,j;
        while (loop--) {
            for (j = starty; j < n - offset; j++)
                num[startx][j] = count++;
            for (i = startx; i < n - offset; i++)
                num[i][j] = count++; 
            for (; j > starty; j--)
                num[i][j] = count++;
            for (; i > startx; i--)
                num[i][j] = count++;
            startx++;
            starty++;
            offset++;
        }
        if (n % 2)
            num[mid][mid] = count;
        return num;

    }
};
// @lc code=end

你可能感兴趣的:(代码随想录算法训练营,算法,leetcode,数据结构)