代码随想录算法训练营第2天|有序数组的平方|长度最小的子数组|螺旋矩阵II
- 有序数组的平方977
题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/
文章讲解:https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html
视频讲解: https://www.bilibili.com/video/BV1QB4y1D7ep
C语言一刷:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
/*
//暴力
*returnSize = numsSize;//*****
int i,j,t;
for(i=0;i<numsSize;i++)
{
nums[i]=nums[i]*nums[i];
}
for(i=0;i<numsSize-1;i++)
{
t=i;
for (j=i+1;j<numsSize;j++)
if(nums[j]<nums[t])
{
t=j;
}
if(i!=t)
{
int tem = nums[i];
nums[i] =nums [t];
nums[t] = tem;
}
}
return nums;
*/
//双指针法
*returnSize = numsSize;
int i, left,right;
int* a = (int*)malloc(sizeof(int) * numsSize);
left =0;
right=numsSize-1;
for(i=numsSize-1;i>=0;i--)
{
if(nums[left]*nums[left]>nums[right]*nums[right])
{
a[i]=nums[left]*nums[left];
left++;
}
else
{
a[i]=nums[right]*nums[right];
right--;
}
}
return a;
}
C++二刷:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> result(nums.size(),0);
int k=nums.size()-1;
for(int i=0,j=nums.size()-1;i<=j;)
{
if(nums[i]*nums[i]<nums[j]*nums[j])
{
result[k--]=nums[j]*nums[j];
j--;
}else
{
result[k--]=nums[i]*nums[i];
i++;
}
}
return result;
}
};
总结
在有序数组中由负到正依次排序,本题求数组中element的平方排序,从一开始就是应用双指针法的思路来解决这道题,由于是由小到大,我就从数组尾部开始比大小,之后来赋值new element,最后得出结果。(这题在江苏理工的笃行杯竞赛里有一道)eg:就像你异世界的战力排行,魔王(负数)和人类(正数)这边,你把正义邪恶的光环去掉,就把他们的战力都平方,然后左右两极开始,在新的战力表里末尾降序战力值。 最后返回新的战力表。
- 长度最小的子数组 209
题目链接:https://leetcode.cn/problems/minimum-size-subarray-sum/
文章讲解:https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html
视频讲解:https://www.bilibili.com/video/BV1tZ4y1q7XE
C语言一刷:
int minSubArrayLen(int target, int* nums, int numsSize) {
int sum=0;
int j=0;
int l=0;
int flag=0;
int min=numsSize;
for(int i=0;i<numsSize;i++)
{
sum=sum+nums[i];
while(sum>=target)
{
l=i-j+1;
if(l<min)
min=l;
sum=sum-nums[j++];
flag=1;
}
}
if (flag!=1)
min=0;
return min;
}
/*
//暴力
int minSubArrayLen(int target, int* nums, int numsSize){
//初始化最小长度为INT_MAX
int minLength = INT_MAX;
int sum;
int left, right;
for(left = 0; left < numsSize; ++left) {
//每次遍历都清零sum,计算当前位置后和>=target的子数组的长度
sum = 0;
//从left开始,sum中添加元素
for(right = left; right < numsSize; ++right) {
sum += nums[right];
//若加入当前元素后,和大于target,则更新minLength
if(sum >= target) {
int subLength = right - left + 1;
minLength = minLength < subLength ? minLength : subLength;
}
}
}
//若minLength不为INT_MAX,则返回minLnegth
return minLength == INT_MAX ? 0 : minLength;
}
*/
C++二刷:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i,resultlength,length,sum;
resultlength=INT32_MAX;
sum=0;
for(int j=0;j<nums.size();j++)
{
sum+=nums[j];
while(sum>=target)
{
length=j-i+1;
resultlength=min(resultlength,length);
sum-=nums[i++];
}
}
return resultlength==INT32_MAX?0:resultlength;
}
};
总结
我自己用滑动窗口的算法解了一下,重要的还是里面的while的作用,分清起始点和终点的区别(本人是起始j,终点i),首先一开始要统计sum,然后你到后面要有与target作比较,在求最小中也就是while的功能,并比较其最小的数值。eg:就像你打吃鸡类的游戏,你们队在梅花桩(圈子中心),然后安全区慢慢缩小,最后你们在房区,决赛圈在前面的空地。你们之中有人大喊:“压缩到最后!涌出去!!!”。(最后对min的return要注意)
- 螺旋矩阵II 59
题目链接:https://leetcode.cn/problems/spiral-matrix-ii/
文章讲解:https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html
视频讲解:https://www.bilibili.com/video/BV1SL4y1N7mV/
C语言一刷:
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {
*returnSize = n;
*returnColumnSizes = (int*)malloc(sizeof(int) * n);
//初始化返回结果数组ans
int** ans = (int**)malloc(sizeof(int*) * n);
int i;
for(i = 0; i < n; i++) {
ans[i] = (int*)malloc(sizeof(int) * n);
(*returnColumnSizes)[i] = n;
}
int x,y,k,c,loop;
x=0;
y=0;
k=1;
c=1;
loop=n/2;
while(loop)
{
int i=x;
int j=y;
for(;j<n-k;j++)
ans[i][j]=c++;
for(; i<n-k;i++)
ans[i][j]=c++;
for(;j>y;j--)
ans[i][j]=c++;
for(;i>x;i--)
ans[i][j]=c++;
x++;
y++;
k++;
loop--;
}
if(n%2==1)
{
ans[x][y]=c;
}
return ans;
}
C++二刷:
*其中一开始有个mylist的初始化,那没啥用不如直接,int size=0; Linknode dummyhead=new Linknode(0);
那玩意就是花架子,不如直接全局写。
class MyLinkedList {
public:
// 初始化链表
struct Linknode
{
int val;
Linknode* next;
Linknode(int val):val(val),next(nullptr){}
};
int size=0;
Linknode* dummyhead=new Linknode(0);
// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点
int get(int index) {
if(index>(size-1)||index<0)
return -1;
Linknode* cur=dummyhead->next;
while(index--)// 如果--index 就会陷入死循环
{
cur=cur->next;
}
return cur->val;
}
// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点
void addAtHead(int val) {
Linknode* newode=new Linknode(val);
newode->next=dummyhead->next;
dummyhead->next=newode;
size++;
}
// 在链表最后面添加一个节点
void addAtTail(int val) {
Linknode* lastnode=new Linknode(val);
Linknode* cur=dummyhead;
while(cur->next!=nullptr)
{
cur=cur->next;
}
cur->next=lastnode;
size++;
}
// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点
// 如果index大于链表的长度,则返回空
// 如果index小于0,则在头部插入节点
void addAtIndex(int index, int val) {
if(index>size) return;
if(index<0) index=0;
Linknode* newnode=new Linknode(val);
Linknode* cur=dummyhead;
while(index--)
{
cur=cur->next;
}
newnode->next=cur->next;
cur->next=newnode;
size++;
}
//删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的
void deleteAtIndex(int index) {
if(index>=size||index<0)
return;
Linknode* cur=dummyhead;
while(index--)
{
cur=cur->next;
}
Linknode* tmp=cur->next;
cur->next=cur->next->next;
delete tmp;
tmp=nullptr;
size--;
}
};
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList* obj = new MyLinkedList();
* int param_1 = obj->get(index);
* obj->addAtHead(val);
* obj->addAtTail(val);
* obj->addAtIndex(index,val);
* obj->deleteAtIndex(index);
*/
总结
这题是对矩阵的考察,听说是有不少企业把其当面试题。在道题求解,就是【)的区间,然后分右下左上的分别4个方向来解题,4个要统一的区间,不然会搞混淆。while里面的loop是由于每次右下左上也就是一圈,一圈会占两行两列,所以就n/2。注意在最后,要对n进行奇偶的判定不然奇数其中间就空元素。eg:四个方向,写一程序,每次占两行两列,然后/2,最后别忘奇条件。(画矩形)