【万人千题】C语言12.2计数总结报告

本文介绍了计数排序的概念及其在非比较排序中的应用,通过解析LeetCode题目展示了如何利用计数排序找到数组中的第K个最大元素。此外,还提供了两种解法解决寻找数组中消失的数字问题,并总结了相关算法题目供读者练习,旨在帮助读者深入理解计数排序和哈希表的使用技巧。
摘要由CSDN通过智能技术生成

目录

一:知识点

1,概念

2,应用

这里给一个题目 ​​​​​​215. 数组中的第K个最大元素 - 力扣(LeetCode) (leetcode-cn.com)

二:习题

   448. 找到所有数组中消失的数字 - 力扣(LeetCode) (leetcode-cn.com)

三:小总结

242. 有效的字母异位词 - 力扣(LeetCode) (leetcode-cn.com)

268. 丢失的数字 - 力扣(LeetCode) (leetcode-cn.com)

389. 找不同 - 力扣(LeetCode) (leetcode-cn.com)

645. 错误的集合 - 力扣(LeetCode) (leetcode-cn.com)


一:知识点

1,概念

今天学习的计数,是最原始的哈希表。

主要的思想在于,把目标数组的每个数映射到另一个计数数组中。

例如,数组arr[0,1,2,3,4,5,6,7,8,9]

我们再开一个数组count[10](注意:这里数组的开的大小主要是根据数据的范围而不是根据目标数组的大小。),那么这个时候我们计数时,++count[ arr[i] ],这时候去遍历arr数组的话,每个对应数组元素的内容就会被映射到count数组中,也就是,count下标对应的就是arr数组中元素的值而count数组中是在计算这个元素有多少个。这样我们就可以得到每个元素的计数了。

2,应用

这种计数方法有个应用在于:排序。我们可以利用它来进行非比较排序

计数排序是一种非比较的排序,它不需要去比较两个元素的大小才进行排序。我们可以把要排序的数组元素映射到count数组中,然后按顺序输出即可。count数组中大小必然是有序,这样逐个输出之后就可以进行排序。不要忘记,count中大于1的话要输出多次,直到变成0.也就是有多个相同元素的时候。

这里给一个题目 ​​​​​​215. 数组中的第K个最大元素 - 力扣(LeetCode) (leetcode-cn.com)

解答如下:

//解法一:
// int cmp(const void*e1,const void*e2)
// {
//     if(*(int*)e1<=*(int*)e2)
//     return 1;
//     else
//     return 0;
// }
// int findKthLargest(int* nums, int numsSize, int k)
// {
//     qsort(nums,numsSize,sizeof(int),cmp);
//     int i=0;
//     for(i=0;i<numsSize;i++)
//     {
//        if(i+1==k)
//          return nums[i];
//     }
//     return 0;
// }
 
//解法二:
int cnt[20001]={0};
int findKthLargest(int* nums, int numsSize, int k)
{
    memset(cnt,0,sizeof(cnt));
    int i=0;
    for(i=0;i<numsSize;i++)
    {
        ++cnt[nums[i]+10000];
    }
    int j=0;
    for(i=0;i<20001;i++)
    {
        while(cnt[i]!=0)
        {
            if(j==numsSize)
            break;
            nums[j]=i-10000;
            j++;
            cnt[i]--;
        }
    }
    //  printf("%d",nums[]);
    for(i=numsSize-1;k;k--,i--)
    {
        if(k-1==0)
        return nums[i];
    }
    return 0;
}

重要:使用计数排序时 如果发现有不是在int类型中的就需要加一个偏移量,比如目标数组的元素数值范围是-100~100,计数时,我们全加上100,让-100变成count数组中的0下标,再进行计数,而等到排完序还原回去时再让每个下标-100即可。

二:习题

   448. 找到所有数组中消失的数字 - 力扣(LeetCode) (leetcode-cn.com)

两种解法:

 int hash[100001];
 int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize)
 {
     memset(hash,0,sizeof(hash));
      int i=0;
      for(i=0;i<numsSize;i++)
      {
          ++hash[nums[i]];
      }
      int *ret=(int*)malloc(sizeof(int)*100000);
      int j=0;
      for(i=1;i<=numsSize;i++)
      {
          if(hash[i]==0)
          {
              ret[j]=i;
              j++;
          }
      }
     *returnSize=j;
      return ret;
 }

解法一的主要思路就是计数,然后遍历cnt的数组,找到在目标范围内没有出现的数即可,

int cmp(const void*e1,const void*e2)
{
     return *(int*)e1-*(int*)e2;
}
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize)
{
     int i=0;
     int *ret=( int*)malloc(sizeof(int)*100000);
     qsort(nums,numsSize,sizeof(int),cmp);
     int j=1;
     int count=0;
     for(i=0;i<numsSize;i++)
     {
    again:
        if(i>0&&nums[i]==nums[i-1])
         continue;
         if(nums[i]==j)
         {
             j++;
             continue;
         }
         else
         {
             ret[count]=j;
             count++;
             j++; 
             goto again;
         }
     }
     for(;j<=numsSize;j++)
         ret[count++]=j;
     *returnSize=count;
     return ret;
}

 解法二就先进行排序,然后i去遍历数组,j来控制需要出现的数。数组中的数有可能出现多次,所进入遍历之后需要判断一下这个是否与前一个相等。判断完后进入下一个判断是否与数组元素相等,相等则证明出现,j++,否则就放入答案数组ret中,然后j++。但是要注意对j最后一个数进行特殊处理。j出来之后,如果不是numsSize就说明自j起到numsSize的数都没有出现过,全部加进去这样就可以啦。

三:小总结

这里还有一些题目,大家可以自己去做做

242. 有效的字母异位词 - 力扣(LeetCode) (leetcode-cn.com)

268. 丢失的数字 - 力扣(LeetCode) (leetcode-cn.com)

389. 找不同 - 力扣(LeetCode) (leetcode-cn.com)

645. 错误的集合 - 力扣(LeetCode) (leetcode-cn.com)

答案在:【万人千题】算法解题报告11.28_C_Ryson的博客-CSDN博客

希望大家可以一起进步呀。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值