LeetCode 977. 有序数组的平方 [难度:简单]

本文介绍了如何使用双指针方法解决非递减排序数组的平方值排序问题,提供了两种不同的双指针策略,分别是从两端向中间遍历和从中间向两端遍历,以及直接平方后再进行排序的解决方案。此外,还提及了快速排序作为备选方案,并讨论了不同方法的时间复杂度。
摘要由CSDN通过智能技术生成

题目

给你一个按 非递减顺序 排序的整数数组 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]

提示:

1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 已按 非递减顺序 排序

进阶:

请你设计时间复杂度为 O(n) 的算法解决本问题

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/squares-of-a-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题

双指针法

原数组是非递减有序的,最大值一定是在两端,所以可以采用双指针法:

比较左指针Left 和 右指针Right 所指元素值的平方的大小

左指针Left 所指的大,那么就将平方值填入新数组的右端,然后Left++;
右指针Right 所指的大,那么就将平方值填入新数组的右端,然后Right–;

重复以上 直到Left > Rgiht;

时间复杂度为O(n);

代码如下

int* sortedSquares(int* nums, int numsSize, int* returnSize)
{
    int* NewNums = malloc(numsSize*sizeof(int));
    *returnSize = numsSize;

	int Left = 0,
        Right = numsSize - 1;
        
    while(Left <= Right){

        if(-nums[Left] >= nums[Right ]){

            NewNums[--numsSize] = nums[Left]*nums[Left];
            
            Left++;
        }else{

            NewNums[--numsSize] = nums[Right ]*nums[Right ];
            Right --;
        }
    }

    return NewNums;
}

以上是从两端往中间遍历,也可以从中间往两端遍历:

i指向最后一个负数,j指向第一个非负数;

比较i所指元素和j所指元素的绝对值

代码如下:

int* sortedSquares(int* nums, int numsSize, int* returnSize)
{
    int i = -1,j;

    while(i+1 < numsSize && nums[i+1] < 0){
        i++;
    }

    j = i+1;
    
    int* NewNums = malloc(numsSize*sizeof(int));
    *returnSize = 0;

    while(i >= 0 && j <= numsSize-1){

        if(-nums[i] <= nums[j]){

            NewNums[*returnSize] = nums[i]*nums[i];
            (*returnSize)++;
            i--;
        
        }else if(-nums[i]  > nums[j]){

            NewNums[*returnSize] = nums[j]*nums[j];
            (*returnSize)++;
            j++;

        }
    }

    while(i >= 0){
        NewNums[*returnSize] = nums[i]*nums[i];
        (*returnSize)++;
        i--;
    }

    while(j <= numsSize - 1){
        NewNums[*returnSize] = nums[j]*nums[j];
        (*returnSize)++;
        j++;
    }

    return NewNums;
}

直接 先平方再排序

来试试笨方法,温习一下排序算法:

调用标准库排序函数qsort

int compare( const void* a,const void* b )
{
    return *(int*)a - *(int*)b;
}

int* sortedSquares(int* nums, int numsSize, int* returnSize)
{
    int i;
    for(i=0;i<numsSize;i++){

        nums[i] *= nums[i];
    }

    *returnSize = numsSize;

    qsort( nums,numsSize,sizeof(int),compare );

    return nums;
}

快速排序

int* sortedSquares(int* nums, int numsSize, int* returnSize)
{
    int i;
    for(i=0;i<numsSize;i++){

        nums[i] *= nums[i];
    }

    *returnSize = numsSize;

    Quicksort( nums,0,numsSize-1 );

    return nums;
}

void Quicksort( int A[],int Left,int Right )
{
	if(Right-Left > 500 ){ //500cutoff,当数组大小小于500时,直接采用插入排序
		
		int pivot,i,j;
		pivot = Median3( A,Left,Right ); //选主元
		i = Left;
		j = Right-1;
		
		while(1){
			
			while(A[++i] < pivot);
			while(A[--j] > pivot);
			
			if(i < j){
				Swap( &A[i],&A[j] );
			}else{
				break;
			}	
		}
		
		Swap( &A[i],&A[Right-1] );
		
		Quicksort( A,Left,i-1 );
		Quicksort( A,i+1,Right );
		
	}else{
		
		Insertion_Sort( A+Left,Right-Left+1 );
	}
}

int Median3( int A[],int Left,int Right )
{
	int Center = (Left+Right)/2;
	
	if(A[Left] > A[Center]){
		Swap( &A[Left],&A[Center] );
	}
	
	if(A[Left] > A[Right]){
		Swap( &A[Left],&A[Right] );
	}
	
	if(A[Center] > A[Right]){
		Swap( &A[Center],&A[Right] );
	}
	
	Swap( &A[Center],&A[Right-1] );
	
	return A[Right-1];
}

void Swap( int* a,int* b )
{
	int Temp = *a;
	*a = *b;
	*b = Temp;
}

void Insertion_Sort( int A[],int N )
{
	int P,i,Tmp;
	for(P=1;P<N;P++){
		Tmp = A[P];
		
		for(i=P;i>=1 && A[i-1]>Tmp;i--){
			A[i] = A[i-1];
		}
		
		A[i] = Tmp;	
	}
}

知识点进阶

数组问题的双指针法应该熟练掌握,灵活应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值