Leetcode 剑指系列 Day 13 双指针

本文详细解析了LeetCode中三道使用双指针技巧的题目:1.调整数组顺序使奇数位于偶数前面;2.和为s的两个数字;3.翻转单词顺序。通过分析解题思路,展示了如何利用双指针有效地解决数组操作和字符串处理问题,并提供了相应的代码实现。这些题目涉及数组操作、快速排序思想和字符串处理技巧,对于提升算法能力十分有帮助。
摘要由CSDN通过智能技术生成

Leetcode 剑指系列 Day 12 双指针

1.剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

解题思路:

从数组首尾同时开始遍历,设置L = 0, R = n - 1;

会有如下四种情况(以Ln, Rn 分别代指左右左右指针所指的指):

(1) Ln为奇数,Rn为偶数 ----> Ln++, Rn–

(2) Ln为偶数,Rn为奇数 ----> 二者交换后 Ln++, Rn–

(3) Ln为奇数, Rn为奇数 ----> Ln++

(4) Ln为偶数, Rn为偶数 ----> Rn–

可得如下代码:

class Solution {
public:
    vector<int> exchange(vector<int>& nums) {
        int L = 0;
        int R = nums.size() - 1;
        while(L < R){
            if(nums[L] % 2 == 1 && nums[R] % 2 == 0){
                L++;
                R--;
            } else if(nums[L] % 2 == 1) {
                L++;
            } else if(nums[R] % 2 == 0) {
                R--;
            } else {
                int temp = nums[L];
                nums[L] = nums[R];
                nums[R] = temp;
            }
        }
        return nums;
    }
};

当然不难发现,这种两个指针向中间聚交换值的样子很像快排

下面是用类快排的解法写的

class Solution {
public:
    vector<int> exchange(vector<int>& nums) {
        int L = 0;
        int R = nums.size() - 1;
        while(L < R){
            while(L < R && nums[L] % 2 == 1) L++;
            while(L < R && nums[R] % 2 == 0) R--;
            int temp = nums[L];
            nums[L] = nums[R];
            nums[R] = temp;
        }
        return nums;
    }
};

2.剑指 Offer 57. 和为s的两个数字

解题思路:

设置双指针 l = 0,r = len - 1

若nums[i] + nums[r] == target 返回这俩值

若nums[i] + nums[r] > target , r–

若nums[i] + nums[r] < target , l++

可得如下代码:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> ans;
        int l = 0, r = nums.size() - 1;
        while(l < r){
            int sum = nums[l] + nums[r];
            if(sum == target){
                ans.push_back(nums[l]);
                ans.push_back(nums[r]);
                return ans;
            } 
            else if(sum > target) r--;
            else l++;
        }
        return ans;
    }
};

3.剑指 Offer 58 - I. 翻转单词顺序

在这里插入图片描述

解题思路:

设i = length - 1; j = length - 1;分别为头尾指针,两指针遍历寻找单词首尾,每找到一个单词,就存入vector apart中,遍历完成后拼接存入string ans并返回。

算法流程:

i = length - 1; j = length - 1;

​ ①、i逐步向前遍历,当i找到第一个非空格字符后,j = i;

​ ②、当i找到一个空格字符后,将s[i+1 ~ j]之间的单词放入apart,i–, 一轮循环结束,循环结束的条件为i >= 0;

​ 当循环退出后,应当判断字符串第一个单词是否插入,此时i = 0

当i向前寻找字符时,分为两种情况:

​ 1.在i = 0前找到了字符,正常插入即可

​ 2.i一直减到了-1也未找到字符,此时意味着没有多余的字符串需要插入,直接退出循环

当i向前寻空格时,分为两种情况

​ 1.在i = 0前找到了空格

​ 2.i一直减到-1也未找到空格,此时意味着从0下标一直到j是需要插入的最后一个字符串,插入完成后while的判断条件i >= 0可以使其退出。

代码如下:

class Solution {
public:
    string reverseWords(string s) {
        string ans;
        int length = s.size();
        vector<string> apart;
        //i为头指针,j为尾指针
        int i = length - 1;
        int j = length - 1; 
        while(i >= 0){
            string temp;
            while(i >= 0){
                if(s[i] == ' ') i--;
                else break;
            }
            //现在i指向了单词的最后一个字符,若i<0说明无字符串需要插入
            if(i >= 0) j = i;
            else break;
            //现在j指向了单词的最后一个字符
            while(i >= 0){
                if(s[i] != ' ') i--;
                else break;
            }
            //现在i指向了单词的前一个空格
            temp.append(s, i + 1, j - i);
            apart.push_back(temp);
        }
        for(int i = 0; i < apart.size(); i++){
            ans += apart[i];
            if(i < apart.size() - 1) ans += " ";
        }
        return ans; 
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值