Leetcode算法入门 - 双指针(一)

10 篇文章 0 订阅
6 篇文章 0 订阅
本文探讨了LeetCode中双指针在977-有序数组的平方和189-轮转数组问题的应用。对于977题,通过双指针从两端相向检查并计算平方值。189题提供了两种解法,一种是使用额外数组,另一种是原地翻转数组。文章详细展示了C和Rust语言的实现,并分析了时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成
  • 双指针的使用策略相比二分查找更丰富些;
  • 使用Rust时 的注意点果然还是比料想的更多;
  • 本专题案例较多,于是便分块记录罢;

目录

Leetcode算法入门之双指针(一)

一、977 - 有序数组的平方

使用双指针相向检查数组两端

二、189 - 轮转数组

方法一、使用额外数组

方法二、翻转数组


Leetcode算法入门之双指针(一)

一、977 - 有序数组的平方

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

示例 1:

输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100] 排序后,数组变为 [0,1,9,16,100] 示例 2:

输入:nums = [-7,-3,2,3,11] 输出:[4,9,9,49,121]

提示:

\noindent1 <= nums.length <= 10^4 \\ -10^4 <= nums[i] <= 10^4 \\

nums 已按非递减顺序排序

使用双指针相向检查数组两端

  • C语言

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
​
int* sortedSquares(int* nums, int numsSize, int* returnSize){
    *returnSize = numsSize;
    int* ans = (int*)malloc(sizeof(int) * (numsSize));
    int i = 0, j = numsSize - 1, t = numsSize - 1;
    while (i <= j) {
        if (nums[i] * nums[i] < nums[j] * nums[j]) {
            ans[t] = nums[j] * nums[j];
            j--;
        } else {
            ans[t] = nums[i] * nums[i];
            i++;
        }
        t--;
    }
    return ans;
}
  • Rust

impl Solution {
    pub fn sorted_squares(nums: Vec<i32>) -> Vec<i32> {
        let mut i = 0;
        let mut j = nums.len() - 1;
        let mut ans: Vec<i32> = Vec::new();
        for index in 0..nums.len() {
            ans.insert(index, 0);
        }
        let mut t = nums.len() - 1;
        while i <= j {
            if nums[i] * nums[i] < nums[j] * nums[j] {
                ans[t] = nums[j] * nums[j];
                j -= 1;
            } else {
                ans[t] = nums[i] * nums[i];
                i += 1;
            }
            t -= 1;
        }
        ans
    }
}
  • 时间复杂度 —— O(n);
  • 空间复杂度 —— O(n);

二、189 - 轮转数组

给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4] 示例 2:

输入:nums = [-1,-100,3,99], k = 2 输出:[3,99,-1,-100] 解释: 向右轮转 1 步: [99,-1,-100,3] 向右轮转 2 步: [3,99,-1,-100]

提示:

1 <= nums.length <= 10^5\\ -2^{31} <= nums[i] <= 2^{31} - 1\\ 0 <= k <= 10^5

使用其中的两种方法来解决

方法一、使用额外数组

  • C语言

void rotate(int* nums, int numsSize, int k) {
    int newArr[numsSize];
    for (int i = 0; i < numsSize; ++i) {
        newArr[(i + k) % numsSize] = nums[i];
    }
    for (int i = 0; i < numsSize; ++i) {
        nums[i] = newArr[i];
    }
}
  • Rust

impl Solution {
    pub fn rotate(nums: &mut Vec<i32>, k: i32) {
        let n = nums.len();
        let mut tmp: Vec<i32> = Vec::new();
        for i in 0..n {
            tmp.insert(i, 0);
        }
        for i in 0..n {
            tmp[(i + k as usize) % n] = nums[i];
        }
        for i in 0..n {
            nums[i] = tmp[i];
        }
    }
}
  • 时间复杂度 —— O(n);
  • 空间复杂度 —— O(n);

方法二、翻转数组

  • C语言

void rev(int* nums, int l, int r) {
    while (l < r) {
        int t = nums[l];
        nums[l] = nums[r];
        nums[r] = t;
        l++, r--;        
    }
}
​
void rotate(int* nums, int numsSize, int k){
    k %= numsSize;
    rev(nums, 0, numsSize - 1);
    rev(nums, 0, k - 1);
    rev(nums, k, numsSize - 1);
}
  • Rust

// 原生算法
pub fn rotate(nums: &mut Vec<i32>, k: i32) {
    let k = k as usize % nums.len();
    let n = nums.len();
    nums.reverse();
    // 切片反转
    nums[0..k].reverse();
    nums[k..n].reverse();
}
​
// 内置方法
pub fn rotate(nums: &mut Vec<i32>, k: i32) {
    let k = k as usize % nums.len();
    nums.rotate_right(k);
}
  • 时间复杂度 —— O(n);
  • 空间复杂度 —— O(1);

每一个不曾起舞的日子,都是对生命的辜负。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_廿_尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值