算法力扣刷题记录三【有序数组的平方】

前言

第三篇尝试,继续。
记录三【有序数组的平方】
力扣题目【977】


一、题目阅读和理解

1.题目阅读

给一个按 非递减顺序 排序的整数数组 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) 的算法解决本问题

2.理解题目

1 数字平方好做,但是加一个递增排序的过程。
2 尝试过程:先写一个功能实现,看是否满足时间复杂度为 O(n) 。


二、第一次尝试下笔

代码实现

先上代码:

class Solution {
public:
    vector<int>& sortedSquares(vector<int>& nums) {  
        int temp = 0;  
        for(int old = 0;old < nums.size();old++){   //old用作原始nums遍历
            nums[old] = nums[old]*nums[old];
            for(int i=old;i > 0;i--){
                if(nums[i-1] > nums[i]){ //找到应该插入的地方            
                     temp = nums[i];
                     nums[i] = nums[i-1];
                     nums[i-1] = temp;                
                }else{
                    break;
                }
            }
        }
        return nums;
    }
};

尝试思路

1 遍历数组,求出每个元素的平方;再对平方进行排序。就算是冒泡排序,时间复杂度是 O(n^2)。
2. 那我就求完平方,就排序出来。
3. 走的弯路:

  • 刚学了双指针,我尝试用两个索引操作同一个数组,比如:

      vector<int> sortedSquares(vector<int>& nums) {
      int new = 0;//用作输出数组的索引
      for(int old = 0;oid < nums.size();old++){   //old用作原始nums遍历
          nums[old] = nums[old]*nums[old];
          for(int i=new;i > 0;i--){
              if(nums[i-1] > nums[i]){ //找到应该插入的地方            
                   temp = nums[i];
                   nums[i] = nums[i-1];
                   nums[i-1] = temp;                
              }else{
                  break;
              }
          }
          new++;                 
     	 }
      }
    
  • 对于内层for循环,我绕了很久。:

      1. 双指针使用:默认一个快一个慢,总是错开的;并且是从同一端出发。new和old初始都是0,最后写出来new和old同步,只用一个old操作就可以。
      2. if找到插入的地方,因为上一条的误区,所以在new=0时,nums[i-1]不合理,浪费了时间。
    
  • 时间复杂度分析:

      1. 内层for循环最坏情况:输入的nums最后一个元素是0,排序时需要往前移动n位。
      2. 外层for循环需要遍历整个数组,元素数量是n。
      3. 所以时间复杂度是O(n^2)。
    
  1. 怎么降低时间复杂度呢?

三、代码随想录学习

学习内容:

1.解法一:每个数平方之后,排个序。
	实现:for循环数组,每个元素都平方替换;再用sort(nums.begin(),nums.end())排序,sort函数快速排序实现,时间复杂度是 O(n + nlogn)。
2. 解法二:使用双指针。
	思路:发现输入数组是从小到大顺序排列,所以平方之后最大值肯定在两端,越往中间,平方值越小。
	所以——很巧妙的把双指针放到数组的两端,逐步往中间靠拢。
	实现:
		vector<int> result;
		int k = nums.size()-1;			//倒着往前填充result数组
		for(int i=0,j=nums.size()-1;i <= j){		//为什么是=,不能漏掉元素
			if(nums[i]*nums[i] > nums[j]*nums[j]){
				result[k] = nums[i]*nums[i] ;    //把大的值放进去
				i++;				//j不需要移动
				//k--;			发现else也需要k--,所以统一放一起。
			}else{								//当nums[i]*nums[i] == nums[j]*nums[j]时,谁先放入result都可以。所以if-else足够。
				result[k] = nums[j]*nums[j] ;
				j--;
									
			}
			k--;	
		}
		return result;//不要忘记返回值。

	时间复杂度分析:i和j从两端向中间靠拢,所以for循环一个数组的大小n,所以结果是O(n)。

改进之处:

1 我写的时间复杂度高,需要改成解法二;
2. 考虑到使用双指针,但是没有用对地方。
3. 没有观察出平方最大值在数组的两端,所以双指针没有用对方法。

总结

  • 双指针使用很灵活:可以从同一端出发,一个快一个慢,使用方法【删除元素】;可以从两端出发,根据条件判断分别移动指针,一个往中间走的快,一个往中间走的慢,步调不一致,使用参考【有序数组的平方】。

(欢迎指正,转载表明出处。)

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值