代码随想录算法训练营第二天:977.有序数组的平方 , 209.长度最小的子数组, 59.螺旋矩阵II
977.有序数组的平方 :
题目链接:977.有序数组的平方
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];
}
//冒泡排序
bubbleSort(ans);
return ans;
}
public void bubbleSort(int[] nums) {
for (int i = 0; i < nums.length - 1; i++) {
for (int j = 0; j < nums.length - i - 1; j++) {
if (nums[j] >= nums[j + 1]) {
int temp = nums[j + 1];
nums[j + 1] = nums[j];
nums[j] = temp;
}
}
}
}
}
总结:
1.思路:全部平方之后再进行冒泡排序:时间复杂度O(n + n*n)
2.双指针方法:最大的数只会出现在数组的两端,构造新的数组,从数组下标最大处存放双指针每次比较的较大值:时间复杂度O(n)
class Solution {
public int[] sortedSquares(int[] nums) {
int[] ans = new int[nums.length];
//双指针法
int index = ans.length - 1;//记录要保存的位置
int left = 0;//左指针
int right = nums.length - 1 ;//右指针
while(right >= left){
int p = nums[left] * nums[left];
int q = nums[right] * nums[right];
if(p > q){
ans[index] = p;
left++;
}else {
ans[index] = q;
right--;
}
index--;
}
return ans;
}
}
209.长度最小的子数组
题目链接:209.长度最小的子数组
public int minSubArrayLen(int target, int[] nums) {
//暴力解法
List list = new ArrayList();
for (int i = 0; i < nums.length; i++) {
int count = 0;
int sum = 0;
for (int j = i; j < nums.length; j++) {
sum = sum + nums[j];
count++;
if(sum >= target){
list.add(count);
break;
}
}
}
if(list.size() == 0)return 0;
int min = (int)list.get(0);
for (int i = 0; i < list.size(); i++) {
if(min > (int)list.get(i))min = (int)list.get(i);
}
return min;
}
总结:
1.暴力解法,两轮循环,超时(18/21),时间复杂度:O(n*n)
2.滑动窗口:不断调节子序列的起始位置和终止位置,得到我们想要的长度:时间复杂度O(n)
class Solution {
public int minSubArrayLen(int target, int[] nums) {
//滑动窗口
int result = Integer.MAX_VALUE;
int left = 0;//起始位置
int subLength = 0;
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum = sum + nums[i];
while(sum >= target){
subLength = i - left + 1;
result = subLength < result ? subLength : result;
sum -= nums[left];
left++;
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
59.螺旋矩阵
题目链接:59.螺旋矩阵
public int[][] generateMatrix(int n) {
int[][] matrix = new int[n][n];
int cnt = 1; // 当前要填充的数字
int i = 0; // 当前行的索引
int j = 0; // 当前列的索引
// 定义四个边界
int rowStart = 0;
int rowEnd = n - 1;
int colStart = 0;
int colEnd = n - 1;
while (cnt <= n * n) {
// 向右走
while (j <= colEnd) {
matrix[i][j] = cnt;
cnt++;
j++;
}
j--; // 修正越界
i++; // 当前行向下移动一行
rowStart++;
// 向下走
while (i <= rowEnd) {
matrix[i][j] = cnt;
cnt++;
i++;
}
i--; // 修正越界
j--; // 当前列向左移动一列
colEnd--;
// 向左走
while (j >= colStart) {
matrix[i][j] = cnt;
cnt++;
j--;
}
j++; // 修正越界
i--; // 当前行向上移动一行
rowEnd--;
// 向上走
while (i >= rowStart) {
matrix[i][j] = cnt;
cnt++;
i--;
}
i++; // 修正越界
j++; // 当前列向右移动一列
colStart++;
}
return matrix;
}
总结:1.i第一想法是想过之前跟韩顺平老师学Java的一个小游戏:每次进行填数的时候分别进行右,下,左,上依次判断,然后填入,时间复杂度:O(n * n )
2.本质是二分法,左开右闭的区间内进行循环,循环 n / 2次,最后判断n是奇数还是偶数,如果是奇数,则最后中心位置在进行赋值,时间复杂度:O(n *n)
class Solution {
public int[][] generateMatrix(int n) {
int[][] matrix = new int[n][n];
int loop = 0;
int number = 1;
int start = 0;
int offset = 1;
int i,j;
while(loop++ < n / 2){
//上面一行
for ( j = start; j < n - offset; j++) {
matrix[start][j] = number++;
}
//右边一列
for (i = start; i < n - offset; i++) {
matrix[i][j] = number++;
}
//下面一行
for (; j >= offset;j--){
matrix[i][j] = number++;
}
//左边一列
for(; i >= offset;i--){
matrix[i][j] = number++;
}
start++;
offset++;
}
if( n % 2 == 1)matrix[n / 2][n / 2] = n * n;
return matrix;
}
}