第一题 LeetCode 278
977. 有序数组的平方https://leetcode-cn.com/problems/squares-of-a-sorted-array/
三种解法:
- 第一种 直接平方后排序
- 第二种 找到正负临界点,再双指针,从中间往两边,存入结果数组。存入的过程先考虑有一边走到头的情况,再考虑比较,类似于归并。
- 第三种 从两边往中间比较,挑出来大的倒着存入结果数组
package Day14.no2;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
/**
* @author ahan
* @create_time 2021-09-27-2:20 下午
*/
public class _977 {
public static void main(String[] args) {
int[] nums = {-7,-3,2,3,11};
_977 soulution = new _977();
int[] ints = soulution.sortedSquares(nums);
for (int i = 0; i < ints.length; i++) {
System.out.print(ints[i] + " ");
}
}
public int[] sortedSquares(int[] nums) {
for (int i = 0; i < nums.length; i++) {
// nums[i] = nums[i] * nums[i];
nums[i] = (int) Math.pow(nums[i], 2);
}
return Arrays.stream(nums).sorted().toArray();
}
public int[] sortedSquares2(int[] nums) {
int[] res = new int[nums.length];
for (int i = 0; i < nums.length; ++i) {
res[i] = nums[i] * nums[i];
}
Arrays.sort(res);
return res;
}
public int[] sortedSquares3(int[] nums) {
int n = nums.length;
int negative = -1;
// 找到临界点
for (int i = 0; i < n; ++i) {
if (nums[i] < 0) {
negative = i;
} else {
break;
}
}
int[] res = new int[n];
int index = 0, i = negative, j = negative + 1;
while (i >= 0 || j < n) {
// 先判断是不是两边有一边走完了的两种情况
if (i < 0) {
res[index] = nums[j] * nums[j];
++j;
} else if (j == n) {
res[index] = nums[i] * nums[i];
--i;
} else if (nums [i] * nums[i] < nums[j] * nums[j]) {
res[index] = nums[i] * nums[i];
--i;
} else {
res[index] = nums[j] * nums[j];
++j;
}
++index;
}
return res;
}
public int[] sortedSquares4(int[] nums) {
int[] res = new int[nums.length];
int left = 0;
int right = nums.length - 1;
int i = right;
while(left <= right){
if(- nums[left] > nums[right]){
res[i] = nums[left] * nums[left];
left += 1;
} else{
res[i] = nums[right] * nums[right];
right -= 1;
}
i--;
}
return res;
}
}
第二题 LeetCode 189. 旋转数组https://leetcode-cn.com/problems/rotate-array/
四种解法:
第一种
数组末尾元素和前面所有元素,从第一个开始到倒数第二个,挨个利用一个临时变量交换。循环k次。会超时。。。
第二种 反转
如 1234567 反转后为7654321
根据k=3, 分为两部分 765 4321
再 分别反转, 567 1234 over~
第三种 环形数组
count 为 k和n的最大公约数 即圈数 (类似辗转相除法)
public int gcd(int x, int y) {
return y > 0 ? gcd(y, x % y) : x;
}
从start = 0,current = start位置开始,利用一个临时变量 prev 存上一个位置的值,和 next = (current + k) % n 位置的值交换,然后再把 next赋值为current。循环构造为do while(start !=current)
第四种
开辟额外的数组存放原数组(复制原数组)news,作为结果的nums数组中的 nums[i],在news数组中找到对应的数组元素即 news[(i+k)%n] 做交换,一一映射。
package Day14.no2;
/**
* @author ahan
* @create_time 2021-09-27-3:39 下午
*/
public class _189 {
public static void main(String[] args) {
int[] nums = {1,2,3,4,5,6,7};
// 567 1234
_189 s = new _189();
s.rotate_1(nums, 5);
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
System.out.println("\n");
int[] nums2 = {1,2,3,4,5,6,7};
s.rotate_reverse(nums2, 3);
for (int i = 0; i < nums2.length; i++) {
System.out.print(nums2[i] + " ");
}
System.out.println("\n");
int[] nums3 = {1,2,3,4,5,6,7};
s.rotate_3(nums3, 4);
for (int i = 0; i < nums3.length; i++) {
System.out.print(nums3[i] + " ");
}
System.out.println("\n");
}
public void rotate_1(int[] nums, int k) {
int n = nums.length;
int[] newArr = new int[n];
for (int i = 0; i < n; ++i) {
newArr[(i + k) % n] = nums[i];
}
System.arraycopy(newArr, 0, nums, 0, n);
}
// 反转
public void rotate_reverse(int[] nums, int k) {
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
}
public void reverse(int[] nums, int start, int end) {
while (start < end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
// 环形替换
public void rotate_3(int[] nums, int k) {
int n = nums.length;
k = k % n;
int count = gcd(k, n);
for (int start = 0; start < count; ++start) {
int current = start;
int prev = nums[start];
do {
int next = (current + k) % n;
int temp = nums[next];
nums[next] = prev;
prev = temp;
current = next;
} while (start != current);
}
}
public int gcd(int x, int y) {
return y > 0 ? gcd(y, x % y) : x;
}
public void rotate_me_nowork(int[] nums, int k) {
int left = 0;
int right = nums.length - 1;
for(int j = right, t = 0;t < k;t++){
while(left < right){
chang(nums, j, left);
left+=1;
}
left = 0;
}
}
private void chang(int[] nums, int a , int b) {
// 第34个测试用例not pass
// nums[a] = nums[a] + nums[b];
// nums[b] = nums[a] - nums[b];
// nums[a] = nums[a] - nums[b];
// 第37个测试用例not pass
// nums[b] = (nums[a] + nums[b]) - (nums[a] = nums[b]);
// 第34个测试用例not pass
// nums[a] = nums[a]^nums[b]; //赋值表达式先不动
// nums[b] = nums[a]^nums[b]; //b = (a^b)^b; b值发生的改变为a的值;
// nums[a] = nums[b]^nums[a]; //a = (a^b)^a; a值也发生了改变;
// 第37个测试用例not pass
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
public void rotate_4(int[] nums, int k) {
int n = nums.length;
int[] news = Arrays.copyOf(nums,n);
for (int i = 0; i < n; i++) {
nums[(i+k)%n] = news[i];
}
}
}