当前位置:   article > 正文

LeetCode数据结构_C语言题解系列-数组II&动态规划_本题思路为:本题有多种算法,较为简单的思路为先通过双重循环找到数组 a[3][3]

本题思路为:本题有多种算法,较为简单的思路为先通过双重循环找到数组 a[3][3]

题目一.两个数组的交集

两个数组的交集 IIhttps://leetcode.cn/problems/intersection-of-two-arrays-ii/

        给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例 :

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]

1.思路分析:

由于要取两个数组的交集,首先想到的方法应该是遍历法,遍历两个数组内相同元素,并且将其送入新数组repty内,返回数组指针repty。其中需要注意以下问题:

1.因为交集数组大小不确定,最大可能为较小数组的长度。repty数组的大小size可设置大一些,重新定义一个int型数据lenth来确定交集范围,否则数组内将会残留未赋值的脏数据;如下图多了一个数:

2.同一数据X出现多次时,交集为min{Xquantity(nums1),Xquantity(nums2)}。即由出现次数少的一个数组决定。特点为:X少的一边必然能在多的一边找到唯一对应。如下图:故在遍历时设置一个标志数组flag即可解决:遍历数组时,当且仅当数据相同且flag==0才为未找过的交集元素,写flag标志位为1,同时break此次循环。

2.AC代码

  1. /**
  2. * Note: The returned array must be malloced, assume caller calls free().
  3. */
  4. int Max(int input1,int input2){
  5. if(input1>=input2) return input1;
  6. else return input2;
  7. }
  8. int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
  9. int size= Max(nums1Size,nums2Size);
  10. int* repty =(int *)malloc(sizeof(int )*Max(nums1Size,nums2Size));
  11. bool* flag =(bool *)malloc(sizeof(bool)*nums2Size);
  12. for(int t=0;t<nums2Size;t++){
  13. flag[t]=0;
  14. }
  15. int k=0;
  16. for(int i=0;i<nums1Size;i++)
  17. {
  18. for(int j=0;j<nums2Size;j++)
  19. {
  20. if(nums1[i]==nums2[j]&&flag[j]==0) {
  21. if(k<size){
  22. repty[k]=nums2[j];
  23. k++;
  24. flag[j]=1;
  25. break;
  26. }
  27. }
  28. }
  29. }
  30. *returnSize=k;
  31. return repty;
  32. }

题目二.买卖股票的最佳时机

121. 买卖股票的最佳时机https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/

        给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 :

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

1.思路分析:

本题为典型的动态规划问题,数据结构使用数组即可。

思路a.暴力遍历

        最简单的思路为二重循环遍历,即设置初始盈利值为一个极小的数-99999,i角标指向当前购买的股票价格,j角标指向卖出股票价格,当prices[j]-prices[i]大于当前盈利值时,刷新当前盈利值。要注意j取值范围为[i+1,pricesSize-1],因为不可以在买入前卖出。

但是该方法在第201个测试用例上会出现超出时间限制问题。如下图所示,该方法不可行。

虽然不能通过该题,但还是将代码给出,以便交流参考。

  1. #define low_price -100000
  2. int maxProfit(int* prices, int pricesSize){
  3. int price_cont=low_price;
  4. for(int i=0;i<pricesSize;i++){
  5. for(int j=i+1;j<pricesSize;j++){
  6. if(prices[j]-prices[i]>=price_cont) {
  7. price_cont=prices[j]-prices[i];
  8. }
  9. }
  10. }
  11. if(price_cont>0)
  12. return price_cont;
  13. else return 0;
  14. }

思路b.动态规划

动态规划 前i天的最大收益 = max{前i-1天的最大收益,第i天的价格-前i-1天中的最小价格},即将第i天前的部分看做一个动态数组,选取其中最小值,与新加入动态数组的元素求利润。当差值大于当前盈利值时,刷新当前盈利值。但是在数组的[0,i-1]范围内选最小值的子函数还是要使用一层循环,本方法同样无法通过第201个测试用例,如下图所示:

虽然不能通过该题,但还是将代码给出,以便交流参考。

  1. #define now_price -99999
  2. #define start 999999
  3. int mins(int* nums,int tail){
  4. int reg=0;
  5. int min=start;
  6. for(int i=0;i<tail;i++){
  7. if(nums[i]<min){
  8. min=nums[i];
  9. reg=i;
  10. }
  11. }
  12. return reg;
  13. }
  14. int maxs(int a,int b){
  15. if(a>=b) return a;
  16. else return b;
  17. }
  18. int maxProfit(int* prices, int pricesSize){
  19. int price_cont=0;
  20. for(int i=0;i<pricesSize;i++){
  21. price_cont=maxs(price_cont,prices[i]-prices[mins(prices,i)]);
  22. }
  23. return price_cont;
  24. }

思路c.极值法

上述两种方法虽然都可以解决问题,但是都使用了二重循环,时间复杂度过高,通不过测试用例。为了压缩用时,回归问题本质:

本质上是买入点越便宜,卖出点越贵越好,即最好是极小值与极大值之差。

故设置变量min=prices[0],如果遍历过程中发现比min小的数据prices[i],刷新min的值,同时记录prices[i]-min,当差值大于当前盈利值时,刷新当前盈利值。这两个步骤可以安排在一层循环内进行,由于min为prices[i]之前(或相同)的值,也保证了“先买后卖”的原则。

2.AC代码

  1. #define now_price -99999
  2. #define start 999999
  3. int maxProfit(int* prices, int pricesSize){
  4. int mincout=prices[0],maxprice=0;
  5. for(int i=0;i<pricesSize;++i)
  6. {
  7. if(prices[i]<mincout) mincout=prices[i];
  8. if(prices[i]-mincout>maxprice) maxprice=prices[i]-mincout;
  9. }
  10. return maxprice;
  11. }

 题目三.重塑矩阵

566. 重塑矩阵icon-default.png?t=N7T8https://leetcode.cn/problems/reshape-the-matrix/

        在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 rc ,分别表示想要的重构的矩阵的行数和列数。重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

示例 :

566. 重塑矩阵

在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。

给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 rc ,分别表示想要的重构的矩阵的行数和列数。

重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。

如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

示例 1:

输入:mat = [[1,2],[3,4]], r = 1, c = 4
输出:[[1,2,3,4]]

1.思路分析:

        首先要理解题目函数框架内入参的含义:如下图所示:二级指针指向一个指针型数组,每一个数组元素指向一个矩阵行,此外还有一个数组matColSize用于表示每一个行有多少数据(列数),在此统一设置为相同值列数即可。

 

 思路非常简单:首先进行判断,若要求输出的矩阵元素个数与原矩阵不相等,返回原数组指针,否则按行优先排序:排序方法有很多,可以通过计算角标的方式得到。但是笔者在这里采用的方法是将行列用新的计数变量k,t表示:新矩阵为row[k][t],数据填满一行时,k++,t置0,未满一行时t++,k不变。由于之前分支考虑过数据不一样多的情况,进入这个分支表示两个矩阵总元素个数必然相同。

2.AC代码

  1. /**
  2. * Return an array of arrays of size *returnSize.
  3. * The sizes of the arrays are returned as *returnColumnSizes array.
  4. * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
  5. */
  6. int** matrixReshape(int** mat, int matSize, int* matColSize, int r, int c, int* returnSize, int** returnColumnSizes){
  7. int t=0;
  8. int k=0;
  9. if(r*c!=(*matColSize)*matSize) {
  10. *returnSize=matSize;
  11. *returnColumnSizes=matColSize;
  12. return mat;
  13. }
  14. else {
  15. *returnSize=r;
  16. *returnColumnSizes=(int*)malloc(r*sizeof(int));
  17. for(int i=0;i<r;i++) (*returnColumnSizes)[i]=c;
  18. int** row=(int**)malloc(r*sizeof(int*));
  19. for(int i=0;i<r;i++){
  20. row[i]=(int*)malloc(c*sizeof(int));
  21. }
  22. for(int i=0;i<matSize;i++){
  23. for(int j=0;j<*matColSize;j++){
  24. row[k][t]=mat[i][j];
  25. if(t<c-1) t++;
  26. else {
  27. k++;
  28. t=0;
  29. }
  30. }
  31. }
  32. return row;
  33. }
  34. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/87253
推荐阅读
相关标签
  

闽ICP备14008679号