【C语言】数组字符串力扣题关键(面试经典)(2)

9、H指数

本题在理解上有一定难度,H指数的题目要求实际上是,在数组的数字里(包含下标)找到一个数H,使他满足:数组元素里H个元素大于等于H。此时参与计算的数有:1、数组总长度n(发表的总论文数)。2、数组下标(第几次发布的论文),3、数组元素(论文被引用的次数)。要求H个元素大于H,为了便于统计我们最好先将数组排序,在这里按从小到大的顺序排列。题目中有一个隐藏信息,即H只有小于n才是有意义的,那么我们从H = n开始向下遍历,此时的H可看做满足被引用的论文的引用次数,可看做下标。

那么满足的元素个数即是符合要求的论文的发布次数(const),const大于等于H时H才有效,所以从右至左的个数(即const)要大于等于H,换在下标里就是第i个元素(包含i,i为const里的第一个元素)往右到数组结束的所有元素都要满足大于等于H,因为从小到大的排序,即(n-H)时就要大于等于H。

int hIndex(int* citations, int citationsSize) {
    int result;
    for(int i = 0;i < citationsSize;i++){
        for(int j = i + 1;j < citationsSize;j++){
            if(citations[i] > citations[j]){
                int temp = citations[i];
                citations[i] = citations[j];
                citations[j] = temp;
            }
        }
    }
    for(int h = citationsSize;h > 0;h--){
        if(citations[citationsSize - h] >= h){
            result = h;
            break;
        }
        else{
            result = 0;//【0】的情况时不能进入if语句,但恒成立
        }
    }
    return result;
}

本题有更多更优解法,但不利于理解。

10、除自身以外数组的乘积

本题的难点在于不能使用除法并且要求了时间复杂度,因此将所有元素乘起来再除以自身和使用for嵌套的方式都不可行。那么可以使用左右乘积列表,思路是除自身以外的数组乘积就是是自身以左的乘积乘自身以右的乘积,那么就以自身i为断点,下标为i的元素的左边的所有乘积放在一个数组(left)里,右边的所有乘积放在一个数组里(right),要求的结果answer数组就是left和right相乘。

int* productExceptSelf(int* nums, int numsSize, int* returnSize) {
    static int answer[100000];
    int left[numsSize];
    int right[numsSize];
    for(int i = 0;i < numsSize;i++){
        if(i == 0){//i等于0的时候没有左边乘积,后续需要使用,因此设为0
            left[i] = 1;
        }
        else{
            left[i] = nums[i - 1] * left[i - 1];
            //原数组的左边一位元素乘之前的所有乘积
        }
    }
    for(int i = numsSize - 1;i >= 0;i--){
        if(i == numsSize - 1){//i等于最后一位的时候没有有边乘积,后续需要使用,因此设为0
            right[i] = 1;
        }
        else{
            right[i] = right[i + 1] * nums[i + 1];
            //原数组的右边一位元素乘之前的所有乘积
        }
    }
    for(int i = 0;i < numsSize;i++){
        answer[i] = left[i] * right[i];
    }
    *returnSize = numsSize;
    return answer;
}

11、罗马数字转整数

根据题意可得罗马数字写法应当是数值从大到小,如有大数在小数右边,则是特殊规则,因此先将罗马数字数组转为阿拉伯数字数组,使用双指针比较相邻俩个数字的大小(i和temp),大数在前则+i,小数在前则-i。

int romanToInt(char* s) {
    int num[15];//题目中给出的数组长度小于等于15
    int result = 0;
    for(int i = 0;i < 15;i++){//初始化数组
        num[i] = 0;
    }
    for(int i = 0;s[i] != '\0';i++){//将罗马数字转为阿拉伯数字
        switch(s[i]){
            case 'I':num[i] = 1;
            break;
            case 'V':num[i] = 5;
            break;
            case 'X':num[i] = 10;
            break;
            case 'L':num[i] = 50;
            break;
            case 'C':num[i] = 100;
            break;
            case 'D':num[i] = 500;
            break;
            case 'M':num[i] = 1000;
            break;
            default:
            break;
        }
    }
    for(int i = 0,temp = 1;temp < 15;i++,temp++){//比较相邻两个数字的大小
        if(num[i] < num[temp]){
            result -=num[i];
        }
        else{
            result += num[i];
        }
    }
    result += num[14];//双指针里用后面的判断结束,因此会少掉最后一位,最后一位不用比较直接相加即可
    return result;
}

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值