977. 有序数组的平方
给你一个按 非递减顺序 排序的整数数组 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
已按 非递减顺序 排序
class Solution { public int[] sortedSquares(int[] nums) { int length=nums.length-1; int[] arr=new int[length+1]; int left=0; int right=length; while(left<=right){ if(nums[left]*nums[left]<nums[right]*nums[right]){ arr[length--]=nums[right]*nums[right]; right--; }else{ arr[length--]=nums[left]*nums[left]; left++; } } return arr; } }
反思
这道题思路不难,但是要注意的是数组边界的问题。
设置的新数组的长度应该跟原数组的一样长,那么接下来就是双指针的用法,这题需要注意的就是要以非递减,那么我们应该留意数组中是否有负数,如果有负数,应该怎么办。
最主要需要判断的是负数的平方和正数的平方哪个大,这样才好排序。设置两个指针,一个指向原数组的头,一个指向尾,比较头尾两个数平方的大小,大的先插入新数组的尾部,(如果是尾部的大,那么指针左移,如果是头部的大,那么指针右移)。时间复杂度是O(n)
189. 轮转数组
给你一个数组,将数组中的元素向右轮转 k
个位置,其中 k
是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:
输入:nums = [-1,-100,3,99], k = 2 输出:[3,99,-1,-100] 解释: 向右轮转 1 步: [99,-1,-100,3] 向右轮转 2 步: [3,99,-1,-100]
提示:
-
1 <= nums.length <= 105
-
-231 <= nums[i] <= 231 - 1
-
0 <= k <= 105
思路
将需要移动的k长度数组直接拷贝到临时数组里,再在原数组的基础上,先把length-k个数往后移动k个位置,再从临时数组把数赋到原数组的前k个位置
class Solution { public void rotate(int[] nums, int k) { k=k%nums.length; if(k==0){ return; } int[] arr=Arrays.copyOfRange(nums,nums.length-k,nums.length); for(int i=nums.length-1;i>=k;i--){ nums[i]=nums[i-k]; } for(int i=0;i<k;i++){ nums[i]=arr[i]; } } }
反思
该题思路应该是没问题,但是要在代码实现上踩坑。
在变化原数组时要考虑数组的长度问题,k位置的数要不要包含。
其他的队列等方法可以之后再进行解决
283. 移动零
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12] 输出: [1,3,12,0,0]
示例 2:
输入: nums = [0] 输出: [0]
提示:
-
1 <= nums.length <= 104
-
-231 <= nums[i] <= 231 - 1
思路
快慢指针:快指针用来处理数据,慢指针用来标记处理好的数据,快指针不断右移,快指针不为0的数赋值给慢指针处,处理完之后将慢指针后面的数值赋0
class Solution { public void moveZeroes(int[] nums) { int slow=0; for(int fast=0;fast<=nums.length-1;fast++){ if(nums[fast]!=0){ nums[slow]=nums[fast]; slow++; } } for(int j=slow;j<=nums.length-1;j++){ nums[j]=0; } } }
反思
关于边界问题
注意数组的最后一个数也要遍历到
167. 两数之和 II - 输入有序数组
给你一个下标从 1 开始的整数数组 numbers
,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target
的两个数。如果设这两个数分别是 numbers[index1]
和 numbers[index2]
,则 1 <= index1 < index2 <= numbers.length
。
以长度为 2 的整数数组 [index1, index2]
的形式返回这两个整数的下标 index1
和 index2
。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。
示例 1:
输入:numbers = [2,7,11,15], target = 9 输出:[1,2] 解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
示例 2:
输入:numbers = [2,3,4], target = 6 输出:[1,3] 解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
示例 3:
输入:numbers = [-1,0], target = -1 输出:[1,2] 解释:-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
提示:
-
2 <= numbers.length <= 3 * 104
-
-1000 <= numbers[i] <= 1000
-
numbers
按 非递减顺序 排列 -
-1000 <= target <= 1000
-
仅存在一个有效答案
思路
双指针的用法,题中给的非递减可以作为参考,如果左右相加大于目标值,右指针左移,如果小于目标值,左指针右移;
最后取下标时一定要记得+1
class Solution { public int[] twoSum(int[] numbers, int target) { int l=0; int r=numbers.length-1; int[] arr=new int[2]; while(l<=r){ if(numbers[l]+numbers[r]<target){ l++; }else if(numbers[l]+numbers[r]>target){ r--; }else{ arr[0]=l+1; arr[1]=r+1; return arr; } } return null; } }