题目:给你一个按 非递减顺序 排序的整数数组 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]
思路:
- 暴力解法:先考虑先把数组遍历,遍历后进行平方运算,把平方运算后的数组放进新数组res[],最后再把新数组*res[]*进行冒泡排序,就达到了非递减顺序的要求。
- 暴力优化解法:先考虑先把数组遍历,遍历后进行平方运算,把平方运算后的数组放进新数组res[],最后再把新数组*res[]*通过Arrays.sort()函数进行排序。
- 双指针算法:leftIndex指向起始位置,rightIndex指向终止位置。定义一个新数组res,和原数组一样的大小,让index指向res数组终止位置。
class Solution {
public int[] sortedSquares(int[] nums) {
int[] res = new int[nums.length];
int temp;
for(int i = 0;i < nums.length;i++){
res[i] = nums[i] * nums[i];
}
for(int i = 0;i < res.length - 1;i++){
for(int j = 0;j < res.length - 1;j++){
if(res[j] > res[j + 1]){
temp = res[j];
res[j] = res[j + 1];
res[j + 1] = temp;
}
}
}
return res;
}
class Solution {
public int[] sortedSquares(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;
}
}
class Solution {
public int[] sortedSquares(int[] nums) {
int rightIndex = nums.length - 1;
int leftIndex = 0;
int[] res = new int[nums.length];
int Index = res.length - 1;
while (leftIndex <= rightIndex) {
if (nums[leftIndex] * nums[leftIndex] > nums[rightIndex] * nums[rightIndex]) {
res[Index--] = nums[leftIndex] * nums[leftIndex];
leftIndex++;
} else {
res[Index--] = nums[rightIndex] * nums[rightIndex];
rightIndex--;
}
}
return res;
}
}
扩展:
-
Arrays.sort()的作用是对括号中的数组进行排序,时间复杂度O(n*logn),方法返回值为void。 是在原来数组的空间基础上进行升序排序,因此不需要定义一个数组接收它,即不需要返回值。 -
Arrays.sort()重载了四类方法: sort(T[] a):对指定T型数组按数字升序排序。 sort(T[] a,int formIndex, int toIndex):对指定T型数组的指定范围按数字升序排序。 sort(T[] a, Comparator<? supre T> c): 根据指定比较器产生的顺序对T型数组进行排序。 sort(T[] a, int formIndex, int toIndex, Comparator<? supre T> c): 根据指定比较器产生的顺序对T型数组的指定范围进行排序。 -
sort(T[] a) 的使用
import java.util.Arrays;
import java.util.Comparator;
public class ArraysSort {
public static void main(String[] args) {
int[] a={2,5,4,3,1,8};
Arrays.sort(a);
System.out.println(Arrays.toString(a));
}
}
- sort(T[] a,int formIndex, int toIndex) 的使用
import java.util.Arrays;
import java.util.Comparator;
public class ArraysSort {
public static void main(String[] args) {
int[] a={2,5,4,3,1,8};
Arrays.sort(a,2,5);
System.out.println(Arrays.toString(a));
}
}
- sort(T[] a, Comparator<? supre T> c)的使用
import java.util.Arrays;
import java.util.Comparator;
public class ArraysSort {
public static void main(String[] args) {
int[][] nums=new int[][]{{1,3},{1,2},{4,5},{3,7}};
Arrays.sort(nums,new Comparator<int[]>(){
@Override
public int compare(int[] a,int[] b){
if(a[0]==b[0]){
return a[1]-b[1];
}else{
return a[0]-b[0];
}
}
});
for (int[] num : nums) {
System.out.println(Arrays.toString(num));
}
}
}
import java.util.Arrays;
import java.util.Comparator;
public class ArraysSort {
public static void main(String[] args) {
int[][] nums=new int[][]{{1,3},{1,2},{4,5},{3,7}};
Arrays.sort(nums,new Comparator<int[]>(){
@Override
public int compare(int[] a,int[] b){
if(a[1]==b[1]){
return a[0]-b[0];
}else{
return a[1]-b[1];
}
}
});
for (int[] num : nums) {
System.out.println(Arrays.toString(num));
}
}
}
- sort(T[] a, Comparator<? supre T> c)类对象比较的使用
import java.util.Arrays;
import java.util.Comparator;
class Dog{
int size;
int weight;
public Dog(int s, int w){
size = s;
weight = w;
}
}
class DogSizeComparator implements Comparator<Dog>{
@Override
public int compare(Dog o1, Dog o2) {
return o1.size - o2.size;
}
}
class DogWeightComparator implements Comparator<Dog>{
@Override
public int compare(Dog o1, Dog o2) {
return o1.weight - o2.weight;
}
}
public class ArraysSort {
public static void main(String[] args) {
Dog d1 = new Dog(2, 50);
Dog d2 = new Dog(1, 30);
Dog d3 = new Dog(3, 40);
Dog[] dogArray = {d1, d2, d3};
printDogs(dogArray);
Arrays.sort(dogArray, new DogSizeComparator());
printDogs(dogArray);
Arrays.sort(dogArray, new DogWeightComparator());
printDogs(dogArray);
}
public static void printDogs(Dog[] dogs){
for(Dog d: dogs)
System.out.print("size="+d.size + " weight=" + d.weight + " ");
System.out.println();
}
}
- 在参数中会出现super,这意味着这类型可以是T或者它的父类型。这就是的该方法可以允许所有子类使用相同的比较器。
import java.util.Arrays;
import java.util.Comparator;
class Animal{
int size;
}
class Dog extends Animal{
public Dog(int s){
size = s;
}
}
class Cat extends Animal{
public Cat(int s){
size = s;
}
}
class AnimalSizeComparator implements Comparator<Animal>{
@Override
public int compare(Animal o1, Animal o2) {
return o1.size - o2.size;
}
}
public class ArraysSort {
public static void main(String[] args) {
Dog d1 = new Dog(2);
Dog d2 = new Dog(1);
Dog d3 = new Dog(3);
Dog[] dogArray = {d1, d2, d3};
printDogs(dogArray);
Arrays.sort(dogArray, new AnimalSizeComparator());
printDogs(dogArray);
System.out.println();
Cat c1 = new Cat(2);
Cat c2 = new Cat(1);
Cat c3 = new Cat(3);
Cat[] catArray = {c1, c2, c3};
printDogs(catArray);
Arrays.sort(catArray, new AnimalSizeComparator());
printDogs(catArray);
}
public static void printDogs(Animal[] animals){
for(Animal a: animals)
System.out.print("size="+a.size + " ");
System.out.println();
}
}
题目:给定一个含有 n 个正整数的数组和一个正整数 target 。
? 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在 符合条件的子数组,返回 0 。
-
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
-
示例 2:
输入:target = 4, nums = [1,4,4] 输出:1
-
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1] 输出:0
思路:
-
暴力算法:最开始就想遍历一遍,判断符合≥target第一遍连续子数组的和,题目要求的是长度最小的连续子数组,所以需要进行嵌套循环,一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环完成了一个不断搜索区间的过程。 枚举数组nums中的每个下标作为子数组的开始下标,对于每个开始下标 i,需要找到大于或等于 i 的最小下标 j,使得从 nums[i] 到nums[j] 的元素和大于或等于 target,并更新子数组的最小长度。(此时子数组的长度是 j - i + 1) 中间思考过为什么是j - i + 1,比如以示例1为例,当第一个for循环的i = 4,即nums[4] = 4,进入第二个for循环中j = 4到j = 5,得出sum = 7,符合≥target(7),所以此时子数组的是nums[4],nums[5],长度为2,count就是5 - 4 + 1,即j - i + 1。 再把每次得到的最小子数组长度进行存储比较,选择其中最小的进行返回。 一开始写完以后基本用例都可以通过,但是运行的时候显示超出时间限制,经过了解发现是LeetCode改了部分测试用例,所以暴力算法的思路算是对的,但是没办法用于这道题目的解答。 -
滑动窗口:通过暴力算法的启发,可以考虑用一个for循环来完成滑动操作。就和Day01中使用过的双指针类似。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int count = 0;
int sum = 0;
int res = Integer.MAX_VALUE;
for(int i = 0;i < nums.length;i++){
sum = 0;
for(int j = i;j < nums.length;j++){
sum += nums[j];
if(sum >= target){
count = j - i + 1;
res = count > res ? res : count;
break;
}
}
}
return res == Integer.MAX_VALUE ? 0 : res;
}
}
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int startIndex = 0;
int count = 0;
int sum = 0;
int res = Integer.MAX_VALUE;
for(int endIndex = 0;endIndex < nums.length;endIndex++){
sum += nums[endIndex];
while(sum >= target){
count = endIndex - startIndex + 1;
res = count > res ? res : count;
sum = sum - nums[startIndex];
startIndex++;
}
}
return res == Integer.MAX_VALUE ? 0 : res;
}
}
扩展:
-
int res = Integer.MAX_VALUE 就是开始把res赋成整型的最大值。然后下面一般都会有个循环,如果res>某个数字,就把res赋值为这个数字,目的是用来找出所有数字中的最小值。 我的理解,设成一个“大数”,目的是用来找出所有数字中的最小值,而Integer.MAX_VALUE又是整型的最大值,可以覆盖绝大部分考虑不到的情况,如果是nums.length + 1,可能会不保险。同理如果是求所有数字中的最大值的话,就可以设成Integer.MIN_VALUE。
题目:给你一个正整数 n ,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
-
示例 1:
输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]]
-
示例 2:
输入:n = 1 输出:[[1]]
思路:考虑顺时针的写法,上行的左→右,右列的上→下,下行的右→左,左列的下→上。需要注意的是区间的定义,左闭右开或左开右闭或左闭右闭。可以考虑一种方式,拐角处让给新的一条边来继续画,即左闭右开。
class Solution {
public int[][] generateMatrix(int n) {
int[][] res = new int[n][n];
int left = 0;
int top = 0;
int right = n - 1;
int buttom = n - 1;
int num = 1;
int sum = n * n;
while(num <= sum){
for(int j = left;j <= right;j++){
res[top][j] = num++;
}
top++;
for(int i = top;i <= buttom ;i++){
res[i][right] = num++;
}
right--;
for(int j = right;j >= left;j--){
res[buttom][j] = num++;
}
buttom--;
for(int i = buttom;i >= top;i--){
res[i][left] = num++;
}
left++;
}
return res;
}
}
总结:
- 经过两天的练习,发现即便题目大不相同,但是内在的思想却大同小异。循环不变量(控制每轮遍历的区间);双指针法(一个指针去找符合条件的元素,一个指针在原地等待),用的很频繁。其中的思想还需要多加体会。
- 也许是第二天的中等题难度多了,练习的时间明显远高于第一天,导致日常计划有所打乱。所以在日后的时间规划上需要进行改进。之前刷过一部分题目,刷完了就过了,没有系统的整理过。这次我就主要把个人思路的变化,以及生疏知识的扩招,按照自己习惯的方式进行记录。先用Typora写好,再发到博客上进行记录。坚持就是胜利,努力为春招做好准备。加油!
|