[解题报告]《算法零基础100讲》(第18讲) 线性枚举(二) - 统计法入门

主要目录

零、写在前面

一、主要知识点

        1.十进制的数位数是否为偶数

        2.前缀和

二、课后习题 

1295. 统计位数为偶数的数字

主要思想

结果分析

540. 有序数组中的单一元素

主要思想

结果分析

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

主要思想

结果分析

1991. 找到数组的中间位置、724. 寻找数组的中心下标

主要思想

结果分析

26. 删除有序数组中的重复项

主要思想

结果分析

1018. 可被 5 整除的二进制前缀

主要思想

结果分析

1015. 可被 K 整除的最小整数

主要思想

结果分析

1869. 哪种连续子字符串更长

主要思想

结果分析

三、今日总结


零、写在前面

         这是打卡的第十八天,今天题目比较简单,就是题量巨大,补充一个知识点,主要知识点在

《算法零基础100讲》(第18讲) 线性枚举(二) - 统计法入门https://blog.csdn.net/WhereIsHeroFrom/article/details/120875708icon-default.png?t=LA46https://blog.csdn.net/WhereIsHeroFrom/article/details/120875708

一、主要知识点

        1.十进制的数位数是否为偶数

        主要利用到的思想就是先确定位数,然后看是否为偶数。

bool weishu(int n){
    int count = 0;    //初始化个数
    while(n){
        count ++;
        n /= 10;        //数数
    }
    return !(count & 1);    //判断是否为偶数
}

        2.前缀和

        有个东西我们可以求一个数组的前缀和,很多题都需要用到。

int pivotIndex(int* nums, int numsSize){
    int total = 0, sum = 0;
    for(int i = 0; i < numsSize;i++)
        total += nums[i];            //统计全和
    for(int i = 0; i < numsSize;sum += nums[i],i++)
        if(sum * 2 == total - nums[i]) return i;    //sum统计前缀和进行判断
    return -1;
}

二、课后习题 

1295. 统计位数为偶数的数字

1295. 统计位数为偶数的数字https://leetcode-cn.com/problems/find-numbers-with-even-number-of-digits/

主要思想

从前到后扫描,用变量计数,更新结果就好了。。看代码

bool weishu(int n){    //判断是否为偶数,看知识点
    int count = 0;
    while(n){
        count ++;
        n /= 10;
    }
    return !(count&1);
}
int findNumbers(int* nums, int numsSize){
    int count = 0;
    for(int i = 0;i < numsSize;i++)
        if(weishu(nums[i])) count++;//满足条件的计数
    return count;
}

结果分析

总觉得,力扣的4ms和0ms差距不大 233


540. 有序数组中的单一元素

540. 有序数组中的单一元素https://leetcode-cn.com/problems/single-element-in-a-sorted-array/

主要思想

利用二分的思想,判断中间的值是否和后面的值相等。其中含有只有一个元素的串的长度一定为奇数。

int singleNonDuplicate(int* nums, int numsSize){
    int low = 0,high = numsSize - 1;//二分初始值
    while(low < high){            //二分跳出条件
        int mid = (low + high) /2;    //二分中间位置
        if(mid % 2 == 1) mid--;        //只判断偶数位
        if(nums[mid] == nums[mid + 1])  low = mid +2;//中间两个相同,所以直接返回高位
        else high = mid;            //无法判断中间位置,但是后面个数为偶数 所以返回前面
    }
    return nums[low];
}

结果分析

凑合,还行。


剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面https://leetcode-cn.com/problems/diao-zheng-shu-zu-shun-xu-shi-qi-shu-wei-yu-ou-shu-qian-mian-lcof/

主要思想

两个指针,一个在前,一个在后,一共往后扫找偶数,一个往前扫找奇数,找到后交换就行了呗。

int* exchange(int* nums, int numsSize, int* returnSize){
    int i = 0 , j = numsSize - 1;
    *returnSize = numsSize;
    while(i < j){
        while((nums[i]&1)&&i < j)  //找到第一个偶数
            i++;
        while((!(nums[j]&1))&& i < j) //找到第一个奇数
            j--;
        if(i < j){
            nums[i] = nums[i] ^ nums[j];//交换i j对应元素
            nums[j] = nums[i] ^ nums[j];
            nums[i] = nums[i] ^ nums[j]; 
        }
        else break;      
    }
    return nums;
}

结果分析

还行吧。


1991. 找到数组的中间位置、724. 寻找数组的中心下标

724. 寻找数组的中心下标https://leetcode-cn.com/problems/find-pivot-index/

1991. 找到数组的中间位置https://leetcode-cn.com/problems/find-the-middle-index-in-array/

主要思想

还记得我知识点说到的前缀和么,就是这道题。。按照说的来就好了。这两道题是一样的一起来吧。

int findMiddleIndex(int* nums, int numsSize){
    int total = 0, sum = 0;
    for(int i = 0; i < numsSize;i++)
        total += nums[i];            //全部和
    for(int i = 0; i < numsSize;sum += nums[i],i++)
        if(sum * 2 == total - nums[i]) return i;//满足条件返回
    return -1;
}

结果分析

可以了


26. 删除有序数组中的重复项

26. 删除有序数组中的重复项https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/

主要思想

统计重复元素,把非重复元素前移就好了。

int removeDuplicates(int* nums, int numsSize){
    int count = 0;
    for(int i = 1;i < numsSize; ++i){
        if(nums[i] == nums[i - count - 1]) //重复元素 统计
            count ++;
        else nums[i - count] = nums[i];     //非重复元素前移
    }
    return numsSize - count;            //返回值
}

结果分析

 简洁,完美


1018. 可被 5 整除的二进制前缀

1018. 可被 5 整除的二进制前缀https://leetcode-cn.com/problems/binary-prefix-divisible-by-5/

主要思想

这道题就是按照要求算就好了,但是要注意会超出范围,及时取余。

返回数组需要malloc,之前之一注意堆栈的我竟然忘了。。。

bool* prefixesDivBy5(int* nums, int numsSize, int* returnSize){
    bool * ans = malloc(sizeof(bool) * numsSize);//申请堆空间
    int temp;       //记录当前值
    *returnSize = numsSize;
    for(int i = 0; i < numsSize; i++){
        temp <<= 1;         //移位2进制
        temp += nums[i];    //将个位插入
        temp %= 5;
        if(temp % 5) ans[i] = false;
        else ans[i] = true;
    }
    return ans;
}  

结果分析

凑合


1015. 可被 K 整除的最小整数

1015. 可被 K 整除的最小整数https://leetcode-cn.com/problems/smallest-integer-divisible-by-k/

主要思想

这个要注意死循环,因为1111生成过程中为*10,所以必然不包含2和5的因子,所以要排除。

int smallestRepunitDivByK(int k){
    if(k % 2 == 0 || k % 5 == 0) return -1;//排除情况
    int temp = 0,i = 0;
    while(++i){
        temp *= 10;
        temp++;
        temp %= k;//及时取余计算防止溢出
        if(temp % k == 0) return i;
    }
    return 0;
}

结果分析

 还行


1869. 哪种连续子字符串更长

1869. 哪种连续子字符串更长https://leetcode-cn.com/problems/longer-contiguous-segments-of-ones-than-zeros/

主要思想

直接统计最大1和最小0的字串比较就好了

bool checkZeroOnes(char * s){
    int max1 = 0,max0 = 0;
    for(int i = 0;s[i] != 0;){    //内部有i++这里不能加i++ 否则结果不对
        int count0 = 0,count1 = 0;
        while(s[i] == '0'){//统计1的数字
            count0 ++;
            i++;
        }
        while(s[i] == '1'){//统计0的数字
            count1++;
            i++;
        }
        max1 = count1 > max1 ? count1 : max1;
        max0 = count0 > max0 ? count0 : max0;
    }
    return max1 > max0;
}

结果分析

 还行


三、今日总结

今天的难度不高,就是题量大,写论文去咯-.-。。。。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XingleiGao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值