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

主要目录

零、写在前面

一、主要知识点

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

        2.前缀和

二、课后习题 

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

主要思想

结果分析

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

主要思想

结果分析

扫描二维码关注公众号,回复: 13420778 查看本文章

剑指 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;
}

结果分析

 还行


三、今日总结

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

猜你喜欢

转载自blog.csdn.net/qq_17593855/article/details/121192212