目录
题目
一、有序数组的平方
- 解题思路:
- 方法一:平方后直接排序
- 方法二:双指针
- 原数组按非递减顺序排列,因此,平方后负数按降序排列,非负数按升序排列;
- 找到整数与负数的分界线,便可得到两个有序的子数组;令负数与非负数的分界线为neg,即nums[0]到nums[neg]为负数,nums[neg+1]到nums[n-1]为非负数;平方后,nums[0]到nums[neg]降序排列,nums[neg+1]到nums[n-1]为升序排列;
- 使用归并排序:使用两个指针分别指向neg和neg+1,每次比较两个指针对应的数,较小的放入答案,并移动指针,继续比较。直至一侧移到边界,将另一侧未遍历的数全部放入。
- 方法三:使用两个指针分别指向0和n-1,每次比较两指针对应的数,较大的逆序放入答案,并移动指针,继续比较。无需处理移至边界的情况。
- 代码:
/* 1 */ class Solution { public int[] sortedSquares(int[] nums) { int[] ans = new int[nums.length]; for(int i = 0; i < nums.length; i++) { ans[i] = nums[i] * nums[i]; } Arrays.sort(ans); return ans; } }
/* 2 */ class Solution { public int[] sortedSquares(int[] nums) { int n = nums.length; int neg = -1; //找分界线 for(int i = 0; i < n; i++){ if(nums[i] < 0) neg = i; else break; } int[] ans = new int[n]; int index = 0, i = neg, j = neg + 1; //排序 while(i >= 0 || j < n) { //两边都未出边界 if(i < 0) { //全为非负数 ans[index] = nums[j] *nums[j]; ++j; } else if(j == n) { //全为负数 ans[index] = nums[i] *nums[i]; --i; } else if(nums[i] * nums[i] < nums[j] * nums[j]) { //选出小的放入结果 ans[index] = nums[i] * nums[i]; --i; } else { ans[index] = nums[j] *nums[j]; ++j; } ++index; } return ans; } }
/* 3 */ class Solution { public int[] sortedSquares(int[] nums) { int n = nums.length; int[] ans = new int[n]; for(int i = 0, j = n-1, index = n - 1; i <= j; ){ if(nums[i] * nums [i] > nums[j] * nums[j]){ //选出大的放入结果 ans[index] = nums[i] * nums[i]; ++i; } else { ans[index] = nums[j] * nums[j]; --j; } --index; } return ans; } }
3. 复杂度分析:
- 方法一
- 时间复杂度:O(nlogn)
- 空间复杂度:O(logn),除了存储数组外,需要 O(logn) 的栈空间进行排序。
- 方法二
- 时间复杂度:O(n)
- 空间复杂度:O(1),除了存储答案的数组O(n)外,只需要维护常量空间。
- 方法三
- 时间复杂度:O(n)
- 空间复杂度:O(1),除了存储答案的数组O(n)外,只需要维护常量空间。
二、旋转数组
- 解题思路:
- 方法一:用新数组存储元素移动k位后的数组,再将其复制回原数组
- 方法二:数组翻转
- 元素移动k位后,尾部k%n位移到数组头部,其余向后移动k%n位;
-
可以将所有元素翻转,尾部元素就被移到了头部,翻转[0,k%n-1]区间和[k%n,n-1]区间得到答案;
- 代码
/* 1 */ class Solution { public void rotate(int[] nums, int k) { int n = nums.length; int[] ans = new int[n]; k %= n; for(int i = 0; i < n; i++){ ans[(i+k)%n] = nums[i]; } System.arraycopy(ans, 0, nums, 0, n); } }
/* 2 */ class Solution { public void rotate(int[] nums, int k) { int n = nums.length; k = k % n; reverse(nums, 0, n - 1); reverse(nums, 0, k - 1); reverse(nums, k, n - 1); } public void reverse(int[] nums, int start, int end){ while(start < end){ //交换start和end int t = nums[start]; nums[start++] = nums[end]; nums[end--] = t; } } }
- 复杂度分析
- 时间复杂度:O(n)
- 空间复杂度:O(1)
总结
想不到,我好废
- System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:要复制的数组
srcPos:要复制数的起始位置
dest:目标数组
destPos:目标数组的下标位置
length:复制的个数