• 【C语言】二级指针的深度理解,峰值的寻找(每日小细节004)


    前言:

    欢迎打开这篇博客,从今天开始,每天和大家分享一个C语言小细节,不久之后还会追加C++

    一些常常被忽视的小细节和思想统一的编程题目是这个专栏的核心哦

    虽然简单但千万别在细节处失分!!!!

    每日花一两分钟浏览一下加深一个知识点不香吗 

    目录

    1.二级指针

    2.峰值 


    1.二级指针

    我们都知道指针变量是保存变量地址的

    1. int main()
    2. {
    3. char a='a';
    4. char* p1=&a;
    5. }

     这里的p1就是一个指针变量(一级指针)因为前面只有一个 * 啊

    事实上我们口头说的p1就是个“指针”其实我们暗指的就是指针变量

    真正的指针就是地址,而指针是存放指针(地址)的变量

    就好比我们说10是整型,但是int a=10;a就是把整型变量,里面存放的是整型数据10

    既然是一个变量就有自己的地址,类型,空间

    指针变量当然不例外

    比如指针变量p1的地址是分配好的,仅从上面的代码我们看不出来

    类型很显然就是char *,char是指 指针指向的数据类型,就是a的类型(char),*是指p是一个指针

    空间内保存的就是a的地址

    那么

    1. int main()
    2. {
    3. char a='a';
    4. char* p1=&a;
    5. char** p2=&p1;
    6. }

    p2就是二级指针变量

    地址依然无法直接看出来

    类型是char** 因为p2指向的  p1  类型是char*,而另一个*代表p2是指针

    空间就是p1的地址 

     所以对p2一次解引用就指向p1

    对p1一次解引用(只能解引用一次)是a的地址,就是指向a

    对p2再次解引用,即对p1解引用,找到的还是a

    更加详细的指针内容请看

    https://blog.csdn.net/weixin_71138261/article/details/126287297?spm=1001.2014.3001.5501

    现在看看这个题目吧

    找出1 2 3 4 哪几处有程序错误? 

    首先1就有错误

    应该是p==NULL或者num<=0 成立一个就return

    void类型的函数里面return就和循环里面的break一样

    所以不是&&而是||  1错误

    此外&str不对,str本来就是指针变量,我们是把字符放在str指向的空间里,而不是把str保存的空间(一个地址)改变

    所以直接写str就可以   3错误

    注:在函数返回之后没有释放内存,但是这不会导致程序错误,只会导致内存泄漏。此题选程序错误所以不算


    2.峰值

    我们发现这个题好简单啊,只要从第二个元素开始遍历,这个元素比旁边两个都大就可以了

    但是这样是片面的

    如果是1 2 3 4 5峰值不在2~4!!!

    9  8  7  6  5  峰值同样不在内部

    所以不要看他给的例子画的图,就是故意诱惑你,写出一般情况

    解决问题有两个手段 :

    1.先写一般情况,发现有错,把特殊情况穷举出来 

    2.直接在“莽夫自杀式”做题之前把各种情况大概思考到位,再动手

    先看第一个方法

    首先如果数组长度是0,没有元素直接返回0就可(把索引值设为0,最后返回索引)

    然后写出else的代码,发现报错,因为只有两个数字根本不能按照

    nums[i] > nums[i - 1] && nums[i] > nums[i + 1]

    这样比较

    所以又补充出else if,当只有两个元素,直接返回最大值(把索引设为在最大数的下标)

    最后最后又没过,因为

    如果是1 2 3 4 5峰值不在2~4!!!

    9  8  7  6  5  峰值同样不在内部

    这些情况没考虑

    所以在最后加上,如果是顺序/逆序,直接把索引设置为长度-1

    1. int findPeakElement(int* nums, int numsLen) {
    2. // write code here
    3. int index = 0;
    4. if (numsLen == 1) index = 0;
    5. else if (numsLen == 2)
    6. {
    7. if (nums[0] > nums[1]) index = 0;
    8. else
    9. index = 1;
    10. }
    11. else {
    12. for (int i = 1; i < numsLen - 1; i++)
    13. {
    14. if (nums[i] > nums[i - 1] && nums[i] > nums[i + 1])
    15. {
    16. index = i;
    17. }
    18. }
    19. if (index == 0 && nums[0] < nums[1])
    20. index = numsLen - 1;
    21. }
    22. return index;
    23. }

    显然这样打补丁很麻烦,万一特例很多这样根本不行

    方法二,观察发现,峰值不一定是在内部,很可能在边界
    这就对应上一种方法的所有特殊情况
    完全可以把第一个元素作为峰值,然后不断比较改变峰值

    1. int findPeakElement(int* nums, int numsLen) {
    2. int index = 0;//定义索引
    3. int max = 0;
    4. if (numsLen == 1) index = 0;
    5. max = nums[0];
    6. int i = 0;
    7. for ( i = 1; i < numsLen; i++)
    8. {
    9. if (nums[i] > max) {
    10. index = i;
    11. max=nums[i];
    12. }
    13. }
    14. return index;
    15. }
    16. int main()
    17. {
    18. int nums[100000] = { 0 }; int numsLen = 0;
    19. scanf("%d", &numsLen);
    20. for (int i = 0; i < numsLen; i++) {
    21. scanf("%d", &nums[i]);
    22. }
    23. int ret = findPeakElement(nums, numsLen);
    24. printf("%d", ret);
    25. }

    创作不易,感谢观看

     

  • 相关阅读:
    python调整colorbar宽度的两种方法
    RSA加密算法
    释放数字生产力 引领数字化转型新纪元——弘玑Cyclone 2022产品发布会圆满落幕
    4.2——Node.js的npm和包
    Python学习的注意点(内容不全,个人学习使用)
    免费SSL证书和付费SSL证书的区别
    c++ 归并排序
    Redis主从复制基础概念
    asyncawait和promise的区别
    [Java反序列化]—C3P0反序列化
  • 原文地址:https://blog.csdn.net/weixin_71138261/article/details/126621762