代码随想录算法训练营第二天| 977. 有序数组的平方、209. 长度最小的子数组、59.螺旋矩阵 II

代码随想录算法训练营第二天| 977. 有序数组的平方、209. 长度最小的子数组、59.螺旋矩阵 II

LeetCode 977题 有序数组的平方

题目链接: 977.有序数组的平方

思路:首先想到的暴力法,先平方然后排序

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
	for (int i = 0; i < nums.size(); i++) {
		nums[i] *= nums[i];
	}
	sort(nums.begin(), nums.end());
	return nums;
  }
};

注:该算法复杂度为O(n+nlogn)

双指针法

思路:该数组本为非递减有序数组,各元素平方后可能会出现负数平方比数组右边元素大的情况
即数组平方的最大值就在数组两端,非左即右,此时可以考虑双指针法

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
	vector<int> result(nums.size(), 0);  //创建一个与nums大小相同全为0的变长数组
	int k = nums.size() - 1;  //对新数组从后往前从大到小插入元素
	for (int left = 0, right = nums.size()-1; left <= right;) {
		if (nums[left] * nums[left] > nums[right] * nums[right]) {
			result[k--] = nums[left] * nums[left];
			left++;
		}
		else {
			result[k--] = nums[right] * nums[right];
			right--;
		}
	}
	return result;
  }
};

此解法复杂度为O(n)。

LeetCode 209题 长度最小的子数组

题目链接: 209.长度最小的子数组

思路:该题第一想法可用暴力解法,使用两个for循环,一个for用于遍历,一个用于数组元素累加直到≥目标值

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
	int result = INT32_MAX;  //定义最终结果,初值设置为最大值
	int subLength = 0;  //定义子序列长度
	for (unsigned int i = 0; i < nums.size() - 1; i++) {
		int sum = 0;  //定义连续数组的和
		for (unsigned int j = i; j < nums.size(); j++) {
			sum += nums[j];  //将数组累加
			if (sum >= s) {  //一旦累和的值大于s
				subLength = j - i + 1;  //得到子序列长度
				result = result < subLength ? result : subLength;
				break;
			}
		}
	}
	return result == INT32_MAX ? 0 : result;
  }
};

注:此解法算法复杂度为O(n^2)。

滑动窗口法

思路:不断调节子序列的起始位置和终止位置,最终得到结果

滑动窗口代码精髓
while (sum >= s) {
subLength = j - i + 1; //得到子序列的长度
result = result < subLength ? result : subLength;
sum -= nums[i++]; //不断变更i(子数组的起始位置)
}

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
	int result = INT32_MAX;
	int subLength = 0;  //滑动窗口长度
	int sum = 0;  //滑动窗口之和
	int i = 0;  //滑动窗口起始位置
	for (int j = 0; j < nums.size(); j++) {
		sum += nums[j];
		while (sum >= s) {
			subLength = j - i + 1;
			result = result < subLength ? result : subLength;
			sum -= nums[i++];
		}
	}
	return result == INT32_MAX ? 0 : result;
 }
};

注:此方法时间复杂度为O(n)

LeetCode 59题 螺旋矩阵 II

题目链接: 35.螺旋矩阵 II

思路:循环不变量!!!

模拟顺时针方向画矩阵
1.从左到右填充上行
2.从上到下填充右列
3.从右到左填充下行
4.从下到上填充左列
注:要坚持循环不变量原则(本题设置为左闭右开区间)

class Solution {
public:
    vector<vector<int> > generateMatrix(int n) {
	vector<vector<int> > res(n, vector<int>(n, 0));
	int startx = 0, starty = 0;  //定义每循环一个圈的起始位置
	int loop = n / 2;  //每个圈循环几次
	int mid = n / 2;  //矩阵中间的位置
	int count = 1;  //用来给矩阵中每一个空格赋值
	int offset = 1;  //每一圈循环都需要控制每一条边遍历的长度
	int i, j;
	while (loop--) {
		i = startx;
		j = starty;
		//下面4个for模拟旋转一圈
		//模拟填充上行从左到右
		for (j = starty; j < starty + n - offset; j++) {
			res[startx][j] = count++;
		}
		//模拟填充右列从上到下
		for (i = startx; i < startx + n - offset; i++) {
			res[i][j] = count++;
		}
		//模拟填充下行从右到左
		for (; j > starty ; j--) {
			res[i][j] = count++;
		}
		//模拟填充左列从下到上
		for (; i > startx; i--) {
			res[i][j] = count++;
		}
		//第二圈开始的时候,起始位置各加1
		startx++;
		starty++;
		//offset用于控制每一圈中每一条边遍历的长度
		offset += 2;
	}
	//如果n为奇数,则需要单独给矩阵最中间的位置赋值
	if (n % 2) {
		res[mid][mid] = count;
	}
	return res;
 }
};

你可能感兴趣的:(代码随想录每日打卡,算法,leetcode,数据结构)