力扣双指针的一些探索

本文介绍了如何利用双指针技巧解决LeetCode中的四个问题:左旋转字符串的操作、检查整数倍数存在、删除有序数组中的重复项、移除特定元素。通过实例演示了如何在不使用额外空间的情况下,高效地修改原数组并返回结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

剑指 Offer 58 - II. 左旋转字符串

题目地址

https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/

题目描述

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

// 示例 1:

输入: s = "abcdefg", k = 2
输出: "cdefgab"

// 示例 2:

输入: s = "lrloseumgh", k = 6
输出: "umghlrlose"

// 限制:
1 <= k < s.length <= 10000

双指针题解
/**
 * @param {string} s
 * @param {number} n
 * @return {string}
 */
var reverseLeftWords = function(s, n) {
    let i = 0, j = n, res = '';
    while(i < n) {
        if(j<s.length) {
            res += s[j];
            j++;
        } else {
            res += s[i];
            i++;
        }
    }
    return res;
};

1346. 检查整数及其两倍数是否存在

题目地址

https://leetcode-cn.com/problems/check-if-n-and-its-double-exist/

题目描述

给你一个整数数组 arr,请你检查是否存在两个整数 N 和 M,满足 N 是 M 的两倍(即,N = 2 * M)。

更正式地,检查是否存在两个下标 i 和 j 满足:

  • i != j
  • 0 <= i, j < arr.length
  • arr[i] == 2 * arr[j]
// 示例 1:

输入:arr = [10,2,5,3]
输出:true
解释:N = 10M = 5 的两倍,即 10 = 2 * 5// 示例 2:

输入:arr = [7,1,14,11]
输出:true
解释:N = 14M = 7 的两倍,即 14 = 2 * 7// 示例 3:

输入:arr = [3,1,7,11]
输出:false
解释:在该情况下不存在 NM 满足 N = 2 * M// 提示:

2 <= arr.length <= 500
-10^3 <= arr[i] <= 10^3
双指针题解
/**
 * @param {number[]} arr
 * @return {boolean}
 */
var checkIfExist = function(arr) {
    let i = 0, j = 0;
    while(i < arr.length) {
        if(arr[i] == 2 * arr[j] && i != j) {
            return true;
        } else {
            j++;
        }
        if(j == arr.length) {
            i++;
            j = 0;
        }
    }
    return false;
}

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

题目地址

https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/

题目描述

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

判题标准:

系统会用下面的代码来测试你的题解:

int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案

int k = removeDuplicates(nums); // 调用

assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
    assert nums[i] == expectedNums[i];
}

如果所有断言都通过,那么您的题解将被 通过。

// 示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

// 示例 2:

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
 

// 提示:

0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按 升序 排列
双指针题解
/**
 * @param {number[]} nums
 * @return {number}
 */
var removeDuplicates = function(nums) {
    let i = 0, j = 0;
    while(j < nums.length) {
        if(nums[i] != nums[j]) {
            i++;
            nums[i] = nums[j];
        }
        j++
    }
    return i+1
};

27. 移除元素

题目地址

https://leetcode-cn.com/problems/remove-element/

题目描述

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

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}
// 示例 1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。

// 示例 2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
 

// 提示:

0 <= nums.length <= 100
0 <= nums[i] <= 50
0 <= val <= 100
双指针题解
/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function(nums, val) {
    let i = 0; j = nums.length - 1;
    while(i <= j) {
        if(nums[i] == val) {
            nums[i] = nums[j];
            j--;
        } else {
            i++;
        }
    }
    return i
};

283. 移动零

题目地址

https://leetcode-cn.com/problems/move-zeroes/

题目描述

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

// 示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

// 示例 2:

输入: nums = [0]
输出: [0]
 

// 提示:

1 <= nums.length <= 104
-231 <= nums[i] <= 231 - 1
 

// 进阶:
你能尽量减少完成的操作次数吗?
双指针解法
/**
 * @param {number[]} nums
 * @return {void} Do not return anything, modify nums in-place instead.
 */
var moveZeroes = function(nums) {
    let len = nums.length
    let j = 0
    for (let i = 0; i < len; i++) {
        if (nums[i]) {
            nums[j++] = nums[i]
        }
    }
    for (let i = j; i < len; i++) {
        nums[i] = 0
    }
    return nums
};

2108. 找出数组中的第一个回文字符串

题目地址

https://leetcode-cn.com/problems/find-first-palindromic-string-in-the-array/

题目描述

给你一个字符串数组 words ,找出并返回数组中的 第一个回文字符串 。如果不存在满足要求的字符串,返回一个 空字符串 “” 。

回文字符串 的定义为:如果一个字符串正着读和反着读一样,那么该字符串就是一个 回文字符串 。

// 示例 1:

输入:words = ["abc","car","ada","racecar","cool"]
输出:"ada"
解释:第一个回文字符串是 "ada" 。
注意,"racecar" 也是回文字符串,但它不是第一个。

// 示例 2:

输入:words = ["notapalindrome","racecar"]
输出:"racecar"
解释:第一个也是唯一一个回文字符串是 "racecar"// 示例 3:

输入:words = ["def","ghi"]
输出:""
解释:不存在回文字符串,所以返回一个空字符串。
 

// 提示:

1 <= words.length <= 100
1 <= words[i].length <= 100
words[i] 仅由小写英文字母组成
双指针题解
/**
 * @param {string[]} words
 * @return {string}
 */
var firstPalindrome = function(words) {
    for(const v of words) {
        if(dp(v)) return v;
    }
    return '';
};

// const dp = s => {
//     return s == s.split('').reverse().join('')
// }

const dp = s => {
    let l = 0;
    let r = s.length - 1;
    while(l <= r) {
        if(s[l] != s[r]) {
            return false;
        } else {
            l++;
            r--;
        }
    }
    return true;
}

1332. 删除回文子序列

题目地址

https://leetcode-cn.com/problems/remove-palindromic-subsequences/

题目描述

给你一个字符串 s,它仅由字母 ‘a’ 和 ‘b’ 组成。每一次删除操作都可以从 s 中删除一个回文 子序列。

返回删除给定字符串中所有字符(字符串为空)的最小删除次数。

「子序列」定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。

「回文」定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。

// 示例 1:

输入:s = "ababa"
输出:1
解释:字符串本身就是回文序列,只需要删除一次。
示例 2:

输入:s = "abb"

// 输出:2
解释:"abb" -> "bb" -> "". 
先删除回文子序列 "a",然后再删除 "bb"// 示例 3:

输入:s = "baabb"
输出:2
解释:"baabb" -> "b" -> "". 
先删除回文子序列 "baab",然后再删除 "b"// 提示:

1 <= s.length <= 1000
s 仅包含字母 'a''b'
双指针解法
/**
 * @param {string} s
 * @return {number}
 */
 var removePalindromeSub = function(s) {
    let L = 0;
    let R = s.length-1;
    while(L<=R){
        if(s[L] !== s[R]){
            return 2;
        }
        L++;
        R--;
    }
    return 1;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SmallTeddy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值