九章算法第七课,两根指针&TwoSum问题

这篇博客介绍了多个数组算法问题的解决方案,如两数之和、奇偶分割数组、颜色分类等,强调了指针在解决问题中的应用,以及如何处理数组的边界条件和移动条件。还提及了数据结构的选择,如哈希表在处理重复元素时的重要性。
摘要由CSDN通过智能技术生成

539. 移动零

class Solution {
public:
    void moveZeroes(vector<int> &nums) {
       if (nums.size()==0) { return; }
       //找到第一个是0的位置;
       int i;
       for (i=0;i<nums.size();i++) {
           if (nums[i]==0) break;
       }
       
       int pos=i; //pos记录下一个不是0的数要换到的位置
       //不管pos上是不是0,只要后面有非0就往前换
       for (i;i<nums.size();i++) {
           if (nums[i]!=0) {
               swap(nums[i],nums[pos]);
               pos++;
           }
       }
    }
};

415. 有效回文串
注意两个内置函数的用法:
transform(字符串头,字符串尾,新字符串头,::tolower||::toupper)
isalnum(char)

class Solution {
public:
    bool isPalindrome(string &s) {
        if (s.length()==0 || s.length()==1) return true;
        transform(s.begin(),s.end(),s.begin(),::tolower);
        
        int i=0; int j=s.length()-1;
        while (i<j) {
            while (!valid(s[i])) i++; //可以用::isalnum(s[i])替代
            while (!valid(s[j])) j--;
            if (i<j && s[i]!=s[j]) return false;
            i++;
            j--;
        }
    }
    bool valid(char c){
        if (c>='0' && c<='9' || c>='a' && c<='z')
            return true;
        else return false;
    }
};

31. 数组划分
注意最后i和j的位置需要判断一下;

class Solution {
public:
    int partitionArray(vector<int> &nums, int k) {
        if (nums.size()==0) return 0;
        
        int i=0;
        int j=nums.size()-1;
        while (i<j) {
            while (i<j && nums[i]<k) i++;
            while (i<j && nums[j]>=k) j--;
            if (i<j) {
                swap(nums[i],nums[j]);
                i++;
                j--;
            }
        }
        if (i==j) return nums[i]<k?i+1:i;
        else return j+1;
    }
};

?461. 无序数组K小元素
思想类似于快排,大体分好左右两部分,确定第k个数在左边还是在右边。由于只需要排一边,时间复杂度O(n)。
注意分割完了之后挑选两部分怎么选。一定要把i,j所在的数包含进去还不能出现划分完了和之前规模一样的情况。
所以需要循环条件设置为(i<=j),移动条件设置为i>pivot和j<pivot;使得ij重合出现在边界的情况不可能出现。

class Solution {
public:
    int kthSmallest(int k, vector<int> &nums) {
        return helper(nums,0,nums.size()-1,k);
    }
    int helper(vector<int>&nums,int start,int end,int k) {
        if (start==end) return nums[start];
        int pivot=nums[(start+end)/2];
        
        int i=start;
        int j=end;
        //要有等号,让i和j交叠或错开,不然可能会出现永远分不开的情况。
        while (i<=j) {
            while (i<=j && nums[i]<pivot) i++;
            while (i<=j && nums[j]>pivot) j--;
            if (i<=j) {
                swap(nums[i],nums[j]);
                i++;
                j--;
            }
        }
        //i,j的位置有两种可能,一种是错开,一种是重合,分情况讨论。
        //不管是错开还是重合,都要保证右边的边界进右边部分,左边的部分进左边部分。
        //如果左右都不是,说明j和i错开了,中间那个就是要找的值。
        if (k<=j-start+1) return helper(nums,start,j,k);
        if (k>=i-start+1) return helper(nums,i,end,k-(i-start));
        return nums[j+1];
    }
};

373. 奇偶分割数组
也是利用快排思想,但是不涉及到二次划分数组,所以不需要考虑会不会分不开的问题。

class Solution {
public:
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值