一、977有序数组的平方
1.1题目
给你一个按 非递减顺序 排序的整数数组 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.2思路分析
先整体求平方,然后对求完平方后的数组排序。
1.3代码实现
方法1暴力求解
先整体求平方,然后使用冒泡算法求完平方后的数组排序。
冒泡排序思想:
冒泡排序外层循环控制的是冒泡的次数 :注意数组最后一个数不要进行冒泡,因此冒泡次数为数组长度减一;
内层循环用于比较大小并更新数组,同理循环的比较条件不但与i有关还与冒泡次数有关因此循环条件为j < nums.length-i-1。
class Solution {
public int[] sortedSquares(int[] nums) {
for(int fast = 0; fast< nums.length; fast++){
nums[fast] = nums[fast]*nums[fast];
}
for(int i = 0; i< nums.length-1; i++){
for(int j = 0 ;j < nums.length-i-1; j++){
int k = 0;
if(nums[j]>nums[j+1]){
k = nums[j];
nums[j] = nums[j+1];
nums[j+1] = k;
}
}
}
return nums;
}
}
方法2双指针
解法思想
使用双指针,定义左指针与右指针。左指针和右指针分别存储数组下标,因为原始数组是有序的,因此平方后的正数的相对位置是不变的,变化比较大的是负数的相对位置;
因此只要改变负数的相对位置即可,我们可以定义一个新的数组,用于存放排序后的值;
则此时的循环条件为左指针小于等于右指针,判断条件则为判断左指针排序后的值是否小于右指针平方后的值,然后将比较后的结果依次存入新定义的数组中。
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0;
int right = nums.length-1;
// 定=定义一个新数组用于存放比较后的结果
int [] new_Nums = new int[nums.length];
// 定义一个新数组的下标
int key = nums.length-1;
while(left <= right){
// 正数的相对位置是不变的,变得是负数因此只需要比较正数和负数的值即可
if(nums[left]*nums[left]>nums[right]*nums[right]){
new_Nums[key] = nums[left]*nums[left];
key--;
left++;
}else{
new_Nums[key] = nums[right]*nums[right];
key--;
right--;
}
}
return new_Nums;
}
}
二、209. 长度最小的子数组
2.1题目
给定一个含有 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
2.2思路分析
计算子数组值与目标值进行比较,然后对子数组的长度进行比较,输出最小长度。
2.3代码实现
方法1暴力求解
定义两个for循环,一个用于存放子数组的起始下标,另一个用于存放子数组的结束下标,(力扣测试时不报错,提交时会报运行超时,不推荐)
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int result = 0;
// 定义最大连续数组的长度
int maxLength = nums.length;
// 定义最小滑动窗口内数组的长度
int minLength = 0;
// i为起始位置
for (int i = 0; i < nums.length; i++) {
// 当初始位置更新时此时的sum应该重新开始
int sum = 0;
for (int j = i; j < nums.length; j++) {
sum += nums[j];
if (sum >= target) {
minLength = j - i + 1;
result = (minLength < maxLength) ? minLength : maxLength;
maxLength = result;
}
}
}
return result;
}
}
方法2滑动窗口
注意循环的起始条件为定义滑动窗口终止位置,滑动窗口的长度为终止位置-起始位置加1;
循环的起始条件为滑动窗口的终止位置而不是起始位置的原因为当为起始位置时,此时使用滑动窗口和暴力求解法没有什么区别。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
// 定义滑动窗口起始位置
int i = 0;
// 定义最大连续数组的长度
int maxLength = nums.length;
// 定义最小滑动窗口内数组的长度
int minLength = 0;
// 定义最后返回的结果
int result = 0;
// 定义滑动窗口内数组的和
int sum = 0;
//以滑动窗口的终止位置为循环的起始点
for(int j = 0; j < nums.length; j++){
sum += nums[j];
// 使用循环比较sum值与目标值
while(sum >= target){
minLength = j - i + 1;
result = (minLength < maxLength) ? minLength : maxLength;
// 将此时的最小程度赋值给最大长度用于下一次的比较
maxLength = result;
sum -= nums[i++];
}
}
return result;
}
}
三、59螺旋矩阵Ⅱ
3.1题目
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
示例 1:
输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入:n = 1 输出:[[1]]
3.2思路分析
整体分为四次遍历,分别为上右下左,在遍历时需注意边界条件,四次边界条件不同。
3.3代码实现
class Solution {
public int[][] generateMatrix(int n) {
int[][] matrix = new int[n][n];
int startX = 0;
int startY = 0;
int offSet = 1;
int count = 1;
// 定义循环变量
int k = 0;
while (k < (n / 2)) {
// 第一圈上边界纵坐标不变
for (int j = startY; j < n - offSet; j++) {
matrix[startX][j] = count++;
}
// 第一圈右边界横坐标不变
for (int i = startX; i < n - offSet; i++) {
matrix[i][n - offSet] = count++;
}
// 第一圈下边界纵坐标不变
for (int j = n - offSet; j> startY; j--) {
matrix[n - offSet][j] = count++;
}
// 第一圈左边界横坐标不变
for (int i = n - offSet; i > startY; i--) {
matrix[i][startY] = count++;
}
startX ++;
startY ++;
offSet ++;
k ++ ;
}
if(n%2 == 1){
matrix[n/2][n/2]= count++;
}
return matrix;
}
}