有关双指针的简单算法题

本文探讨了使用双指针解决多种算法问题,包括移动零、反转字符串、求有序数组的交集、最大升序子数组和等。并提供了相关LeetCode题目以供练习。
摘要由CSDN通过智能技术生成

有关双指针

1. 移动零(附leetcode.283)

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
方法一:双指针
思路:
使用双指针,左指针指向当前已经处理好的序列的尾部,右指针指向待处理序列的头部。
右指针不断向右移动,每次右指针指向非零数,则将左右指针对应的数交换,同时左指针右移。
注意到以下性质:
1.左指针左边均为非零数;
2.右指针左边直到左指针处均为零。
因此每次交换,都是将左指针的零与右指针的非零数交换,且非零数的相对顺序并未改变。
void swap(int *a, int *b) {
    int t = *a;
    *a = *b, *b = t;
}

void moveZeroes(int *nums, int numsSize) {
    int left = 0, right = 0;
    while (right < numsSize) {
        if (nums[right]) {
            swap(nums + left, nums + right);
            left++;
        }
        right++;
    }
}
方法二:二次遍历 java实现
思路:
我们创建两个指针i和j,第一次遍历的时候指针j用来记录当前有多少非0元素。即遍历的时候每遇到一个非0元素就将其往数组左边挪,第一次遍历完后,j指针的下标就指向了最后一个非0元素下标。
第二次遍历的时候,起始位置就从j开始到结束,将剩下的这段区域内的元素全部置为0。
class Solution {
	public void moveZeroes(int[] nums) {
		if(nums==null) {
			return;
		}
		//第一次遍历的时候,j指针记录非0的个数,只要是非0的统统都赋给nums[j]
		int j = 0;
		for(int i=0;i<nums.length;++i) {
			if(nums[i]!=0) {
				nums[j++] = nums[i];
			}
		}
		//非0元素统计完了,剩下的都是0了
		//所以第二次遍历把末尾的元素都赋为0即可
		for(int i=j;i<nums.length;++i) {
			nums[i] = 0;
		}
	}
}
方法三:一次遍历
这里参考了快速排序的思想,快速排序首先要确定一个待分割的元素做中间点x,然后把所有小于等于x的元素放到x的左边,大于x的元素放到其右边。
这里我们可以用0当做这个中间点,把不等于0(注意题目没说不能有负数)的放到中间点的左边,等于0的放到其右边。
这的中间点就是0本身,所以实现起来比快速排序简单很多,我们使用两个指针i和j,只要nums[i]!=0,我们就交换nums[i]和nums[j]
class Solution {
	public void moveZeroes(int[] nums) {
		if(nums==null) {
			return;
		}
		//两个指针i和j
		int j = 0;
		for(int i=0;i<nums.length;i++) {
			//当前元素!=0,就把其交换到左边,等于0的交换到右边
			if(nums[i]!=0) {
				int tmp = nums[i];
				nums[i] = nums[j];
				nums[j++] = tmp;
			}
		}
	}
}	




2.反转字符串(附leetcode 344)
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
示例:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]
方法一:双指针
void reverseString(char* s, int sSize){
    for (int i = 0, j = sSize - 1; i < j; ++i, --j) {
        /* 不断 swap(s[i], s[j]) */
        char c = s[i];
        s[i] = s[j];
        s[j] = c;
    }    
}
//另一种写法
void reverseString(char* s, int sSize){
    int p,q;
    p=0;
    q=sSize-1;
    char temp;
    while(p<q){
        temp=s[q];
        s[q]=s[p];
        s[p]=temp;
        p++;
        q--;
    }
}



3.有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
//方法一:冒泡排序   注意:会超时
int* sortedSquares(int* nums, int numsSize, int* returnSize){
    *returnSize=numsSize;
    int j=0;
    for(int i=0;i<numsSize;i++){
        nums[j++]=nums[i]*nums[i];
    }
    int temp;
    //排序
    for(int i=0;i<numsSize;i++){
        for(int k=0;k<numsSize-i-1;k){
            if(nums[k+1]>nums[k]){
                temp=nums[k+1];
                nums[k+1]=nums[k];
                nums[k]=temp;
            }
        }
    }
    return nums;
}
另一种写法:
int* sortedSquares(int* nums, int numsSize, int* returnSize){
    *returnSize=numsSize;
    int *ans=malloc(sizeof(int)*numsSize);//申请数组空间
    for(int i=0;i<numsSize;i++){
        ans[i]=nums[i]*nums[i];
    }
    int temp;
    //排序
    for(int i=0;i<numsSize;i++){
        for(int k=0;k<numsSize-i-1;k){
            if(ans[k+1]>ans[k]){
                temp=ans[k+1];
                ans[k+1]=ans[k];
                ans[k]=temp;
            }
        }
    }
    return ans;
}
//方法二:双指针
int* sortedSquares(int* a, int n, int* returnSize){
*returnSize=n;
if(n==0) return a;
int p=0,q=-1;
for(int i=0;i<n;i++){
	if(a[i]>=0) {
		p
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值