2022-6-16 滑动窗口最大值,数组中的k-diff数对,下一个排列,搜索旋转排序数组

1. 滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值

Example 1

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

Example 2

输入:nums = [1], k = 1
输出:[1]

Constraints:

  • 1 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10^4
  • 1 <= k <= nums.length

代码 [双端队列]

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int> &nums, int k) {
        deque<int> q; // idx
        auto push = [&](int idx) {
            if (!q.empty() && q.front() == idx - k) q.pop_front();
            while (!q.empty() && nums[q.back()] < nums[idx]) q.pop_back();
            q.push_back(idx);
        };
        vector<int> result;
        for (int i = 0; i < nums.size(); ++i) {
            push(i);
            if (i + 1 >= k) result.push_back(nums[q.front()]);
        }
        return result;
    }
};

2. 数组中的 k-diff 数对

给你一个整数数组 nums 和一个整数 k,请你在数组中找出 不同的 k-diff 数对,并返回不同的 k-diff 数对 的数目。

k-diff 数对定义为一个整数对 (nums[i], nums[j]) ,并满足下述全部条件:

  • 0 <= i, j < nums.length
  • i != j
  • nums[i] - nums[j] == k

注意|val| 表示 val 的绝对值。

Example 1

输入:nums = [3, 1, 4, 1, 5], k = 2
输出:2
解释:数组中有两个 2-diff 数对, (1, 3) 和 (3, 5)。
尽管数组中有两个 1 ,但我们只应返回不同的数对的数量。

Example 2

输入:nums = [1, 2, 3, 4, 5], k = 1
输出:4
解释:数组中有四个 1-diff 数对, (1, 2), (2, 3), (3, 4) 和 (4, 5) 。

Constraints:

  • 1 <= nums.length <= 10^4
  • -10^7 <= nums[i] <= 10^7
  • 0 <= k <= 10^7

代码 [哈希]

class Solution {
public:
    int findPairs(vector<int> &nums, int k) {
        unordered_set<int> uset, result;
        for (int x:nums) {
            if (uset.count(x - k)) result.insert(x - k);
            if (uset.count(x + k)) result.insert(x);
            uset.insert(x);
        }
        return result.size();
    }
};

3. 下一个排列

A permutation of an array of integers is an arrangement of its members into a sequence or linear order.

  • For example, for arr = [1,2,3], the following are considered permutations of arr: [1,2,3], [1,3,2], [3,1,2], [2,3,1].

The next permutation of an array of integers is the next lexicographically greater permutation of its integer. More formally, if all the permutations of the array are sorted in one container according to their lexicographical order, then the next permutation of that array is the permutation that follows it in the sorted container. If such arrangement is not possible, the array must be rearranged as the lowest possible order (i.e., sorted in ascending order).

  • For example, the next permutation of arr = [1,2,3] is [1,3,2].
  • Similarly, the next permutation of arr = [2,3,1] is [3,1,2].
  • While the next permutation of arr = [3,2,1] is [1,2,3] because [3,2,1] does not have a lexicographical larger rearrangement.

Given an array of integers nums, find the next permutation of nums.

The replacement must be in place and use only constant extra memory.

Example 1

Input: nums = [1,2,3]
Output: [1,3,2]

Example 2

Input: nums = [3,2,1]
Output: [1,2,3]

Constraints:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 100

代码 1 [O(nlogn)]

class Solution {
public:
    void nextPermutation(vector<int> &nums) {
        int i = nums.size();
        while (--i > 0 && nums[i - 1] >= nums[i]);
        int idx_1 = i - 1, idx_2 = i;
        if (i > 0) {
            for (int j = i; j < nums.size(); ++j) {
                if (nums[j] > nums[idx_1] && nums[j] < nums[idx_2]) idx_2 = j;
            }
            swap(nums[idx_1], nums[idx_2]);
        }
        sort(nums.begin() + i, nums.end());
    }
};

代码 2 [O(n)]

代码1对于idx_1之后的所有元素使用快速排序,然而,只要保证idx_2是满足交换条件的最后一个元素,进行交换操作后,idx_1之后的元素递减,因此只需倒序即可。

class Solution {
public:
    void nextPermutation(vector<int> &nums) {
        int i = nums.size();
        while (--i > 0 && nums[i - 1] >= nums[i]);
        int idx_1 = i - 1, idx_2 = i;
        if (i > 0) {
            for (int j = i; j < nums.size(); ++j) {
                if (nums[j] > nums[idx_1] && nums[j] <= nums[idx_2]) idx_2 = j; // 此处与代码1不同
            }
            swap(nums[idx_1], nums[idx_2]);
        }
        int j = nums.size() - 1;
        while (i < j) swap(nums[i++], nums[j--]);
    }
};

4. 搜索旋转排序数组

There is an integer array nums sorted in ascending order (with distinct values).

Prior to being passed to your function, nums is possibly rotated at an unknown pivot index k (1 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]] (0-indexed). For example, [0,1,2,4,5,6,7] might be rotated at pivot index 3 and become [4,5,6,7,0,1,2].

Given the array nums after the possible rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.

You must write an algorithm with O(log n) runtime complexity.

Example 1

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1

Constraints:

  • 1 <= nums.length <= 5000
  • -10^4 <= nums[i] <= 10^4
  • All values of nums are unique.
  • nums is an ascending array that is possibly rotated.
  • -10^4 <= target <= 10^4

代码 [二分]

class Solution {
public:
    int search(vector<int> nums, int target) {
        int lo = 0, hi = nums.size() - 1;
        while (lo <= hi) {
            int mi = (lo + hi) >> 1;
            if (nums[mi] == target) return mi;
            if (nums[lo] <= nums[mi]) {
                nums[lo] <= target && target < nums[mi] ? hi = mi - 1 : lo = mi + 1;
            } else {
                nums[mi] < target && target <= nums[hi] ? lo = mi + 1 : hi = mi - 1;
            }
        }
        return -1;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值