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

977.有序数组的平方

题目链接:link
视频链接:link
文章讲解链接:link

一、做题感受&第一想法

犯的小错:
①一开始returnSize没赋值,导致没有输出。
②重复使用了i,但是第二次使用时while循环前没有给i赋初值。
③定义数组时,数组大小用了变量(C语言不允许这样),导致报错。
第一想法:双指针(但略麻烦,还可以改进。麻烦主要在各种边界的判断上。)

int* sortedSquares(int* nums, int numsSize, int* returnSize) {
    int i = 0, j = -1, k = 0;
    int *newNums = (int*)malloc(sizeof(int)*numsSize);
    for(i = 0; i < numsSize; i++) //找到负数正数的分界点,记录在j中
    {
        if(nums[i] < 0){
            j++;
            nums[i] = nums[i]* nums[i];
        }
        else if(nums[i] >= 0)
        {
            nums[i] = nums[i]* nums[i];
        }
    }
    i = j + 1; //重复使用了i作为循环变量,不要忘记初始化
    while((j >= 0) || (i < numsSize)){ //当正数、负数有一方没有被完全遍历时,继续循环
        if((j >= 0 && i < numsSize && nums[i] < nums[j]) || (j < 0 && i < numsSize)){
            newNums[k] = nums[i];
            k++;
            i++;
        }
        else if((j >= 0 && i < numsSize && nums[i] >= nums[j]) || (j >= 0 && i >= numsSize)){
            newNums[k] = nums[j];
            k++;
            j--;
        }
    }
    * returnSize = numsSize; //leetcode平台不要忘记赋值returnSize。
    return newNums;
}

二、学习文章后收获

1.双指针法

  • 一头一尾开始,往中间遍历 (因为最大的一定在两边)
  • 比较时运用归并排序的思想。需要额外的数组空间,空间复杂度O(n)。
  • 返回的数组是从后往前遍历的(一个以后可借鉴的思路),因为归并排序排出来的是从大到小。
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
    int i = 0, j = numsSize - 1, k = numsSize - 1;
    int * returnNums = (int *) malloc(sizeof(int)*numsSize);
    while(i<=j){
        if(nums[i]*nums[i] < nums[j]*nums[j] ){
            returnNums[k] = nums[j] * nums[j];
            k--;
            j--;
        }
        else{
            returnNums[k] = nums[i] * nums[i];
            i++;
            k--;
        }
    }
    * returnSize = numsSize;
    return returnNums;
}

三、实现过程中的困难

1.C语言中直接定义数组,数组大小不能用变量。(但可以通过malloc解决)

报错:
solution.c: In function ‘sortedSquares’
Line 6: Char 5: error: variable-sized object may not be initialized [solution.c]
9 | int newNums[numsSize] = {0};
| ^~~


209.长度最小的子数组

题目链接:link
文章讲解:link
视频讲解:link

一、做题感受&第一想法

只想到暴力解法。最后超出时间限制。

二、学习文章后收获

1.双指针:滑动窗口法

#define INT_MAX 100001

int minSubArrayLen(int target, int* nums, int numsSize) {
    int j = 0, i = 0, length = INT_MAX, sum = 0;
    for( j = 0; j < numsSize; j++ ){
        sum += nums[j];
        while(sum >= target){
            length = (length > j-i+1) ? (j-i+1) : length;
            sum -= nums[i];
            i++;
        }
    }
    return (length == INT_MAX) ? 0 : length;
}
  • j:滑动窗口的结束位置。一直加加,直到最后。
  • i:滑动窗口的开始位置。只有需要时才更新。
  • length:记录找到的最小滑动窗口的长度。每找到一个滑动窗口就更新一次。

三、实现过程中的困难

1.灵活使用 ? : 运算符

简单的条件判断可用该运算符。可以减少分支语句的使用。

2.有时可设置极大值MAX,以便于编程。


59.螺旋矩阵Ⅱ

题目链接:link
文章讲解:link
视频讲解:link

一、做题感受&第一想法

①不会申请二维数组。
②螺旋矩阵赋值时,对某些元素重复赋值了(旋转换方向时,把四个角上的元素重复赋值了,属于逻辑上没想清楚的错误。)

int** generateMatrix(int n, int* returnSize, int** returnColumnSizes) {
    *returnSize = n;
    *returnColumnSizes = (int *)malloc(sizeof(int)*n);
    int ** matrix = (int** )malloc(sizeof(int*) * n);
    for(int i = 0; i < n; i++){
        matrix[i] = (int *)malloc(sizeof(int)*n);
        (*returnColumnSizes)[i] = n;
    }

    int k = 1, t = 0, i = 0;
    while(k<=n*n){
        for(i = t; i < n-t && k <= n*n; i++){
            matrix[t][i] = k;
            k++;
        }
        for(i = t+1; i < n-t && k <= n*n; i++){
            matrix[i][n-t-1] = k;
            k++;
        }
        for(i = n-t-1-1; i >= t && k <= n*n; i--){
            matrix[n-t-1][i] = k;
            k++;
        }
        for(i = n-t-1-1; i >= t+1 && k <= n*n; i--){
            matrix[i][t] = k;
            k++;
        }
        t++;
    }
    return matrix;
}

二、学习文章后收获

三、实现过程中的困难

1.关于c语言中申请二维数组

	int ** p = (int **)malloc(sizeof(int*) * row);
	
	for(int i = 0; i < row; i++){
		p[i] = (int *)malloc(sizeof(int) * col);
	}

2.leetcode平台下的二维数组大小返回值

 //Return an array of arrays of size *returnSize.
 //The sizes of the arrays are returned as *returnColumnSizes array.
    *returnSize = n; //共有几个数组(行数)
    *returnColumnSizes = (int *)malloc(sizeof(int)*n);
    int ** matrix = (int** )malloc(sizeof(int*) * n);
    for(int i = 0; i < n; i++){
        matrix[i] = (int *)malloc(sizeof(int)*n);
        (*returnColumnSizes)[i] = n; //记录每个数组的大小,即每个数组的元素个数(列数)
    }

3.数组、二维数组、指针的关系

int arr[3] = {1,2,3}; 
int* pa = arr; 

(1)数组地址&arr、数组名arr、数组第一个元素地址arr[0],三者都是“地址”值,三者相同!
(2)数组名arr可以认为是指针常量,无法改变。
(3)对于“指向数组元素的指针”pa
①可以用pa[0] pa[1] pa[2]来取数组元素。
②也可以pa = pa + 1来改变pa的指向,此时pa指向第二个元素pa[1](因为对指针变量加减n,实际地址改变n*sizeof(类型)的大小。)。
③也可以用*pa来取数组元素。

int arr[3] = {1,2,3}; 
int (*parr)[] = &arr; 

(4)对于“指向数组类型的指针”parr
①定义格式:int (*parr)[] = &arr(为什么加括号?因为[]优先级高于*。)

在这里插入图片描述

注:截图来自up主:哈哈哈哈栋。
链接:link

②如何取数组元素:(*parr)[0], (*parr)[1], (*parr)[2](可以理解为*parr == arr)

(5)“指针数组”(数组的元素是指针)p

int a = 1, b = 2;
int *p[2] ={&a , &b};

①如何取元素:*p[0], *p[1]

(6)混合型:

在这里插入图片描述
要想取出元素值:*(*parr)[0], *(*parr)[1], *(*parr)[2]

(二维数组,待补充。)

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
第二十二算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组平方",和Leetcode 209 "长度最小数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小数组,使得数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值