刷题笔记

67 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


NC31第一个只出现一次的字符

解题思路

基本思路就是把出现的字符当作下标,每出现一次就加一。

最后遍历一遍,返回出现1的下标,否则就返回-1.

为了减少空间的浪费,我们只需要开A到z空间的大小。

代码

int FirstNotRepeatingChar(char* str ) {
    int n=('z'-'A'+1);
    int len=strlen(str);
    int* a=(int*)malloc(sizeof(int)*n);
    memset(a, 0,sizeof(int)*n);
    for(int i=0;i<len;i++)
    {
        a[str[i]-'A']++;
    }
    for(int i=0;i<len;i++)
    {
        if(a[str[i]-'A']==1)
        {
            free(a);
            return i;
        }
    }
    free(a);
    return -1;
}

面试题01.01.判定字符是否唯一

解题思路

1.暴力的方法就是一个字符固定,然后和后面的一个一个进行比较

2.因为题目说明了都是小写字母image-20220711195345548

所以我们从新创建一个空间,以字符的大小为下标,出现一次就在以该字符为下标的地方加1。

最后只需要遍历一下,只要没有出现不为1的,就是true,否则为false。

代码

  • 暴力:==时间复杂度O(N*N),空间复杂度O(1)==
bool isUnique(char* astr){
    int len=strlen(astr);
    int i,j;
    for(i=0;i<len;i++)
    {
        for(j=i+1;j<len;j++)
        {
            if(astr[i]==astr[j])
            return false;
        }
    }
    return true;
}
  • 另一种方法,==时间复杂度O(N),空间复杂度O(1)==
bool isUnique(char* astr){
    int len=strlen(astr);
    int n='z'-'a'+1;
    int* s=(int*)malloc(sizeof(int)*n);
    memset(s,0,sizeof(int)*n);
    for(int i=0;i<len;i++)
        s[astr[i]-'a']++;
    for(int i=0;i<len;i++)
    {
        if(s[astr[i]-'a']!=1)
        {
            free(s);
            return false;
        }
    }
    free(s);
    return true;
}

349.两个数组的交集

解题思路

暴力解题:

num1数组中的每一个元素跟num2的每一个元素进行比较,当相同时,就察看它是否出现在交集的数组中,不存在就添加进去。

代码

int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
    int* array=(int*)malloc(sizeof(int)*nums1Size);
    int i,j;
    int x=0;
    for(i=0;i<nums1Size;i++)
    {
        for(j=0;j<nums2Size;j++)
        {
            if(nums1[i]==nums2[j])
                break;
        }
        if(j==nums2Size)
        continue;
        for(j=0;j<x;j++)
        {
            if(nums1[i]==array[j])
            break;
        }
        if(j==x)
        array[x++]=nums1[i];
    }
    *returnSize=x;
    return array;
}

724.寻找数组的中心下标

解题思路

暴力解题:

i为中心下标,用j来控制左边和右边,然后判断左边和右边是否相同。相同则返回i,直到遍历完整个数组也没有出现相同,就返回-1

代码

int pivotIndex(int* nums, int numsSize){
    int i,j;
    for(i=0;i<numsSize;i++)
    {
        int leftsum=0,rightsum=0;
        for(j=0;j<numsSize;j++)
        {
            if(j<i)
            leftsum+=nums[j];
            if(j>i)
            rightsum+=nums[j];
        }
        if(leftsum==rightsum)
        return i;
    }
    return -1;
}

NC107寻找峰值

思路

暴力遍历

从头开始遍历,只要出现左边大于右边的就找到该峰值了。

二分:

中间的大于右边的,说明左边有峰值。

中间的小于右边的,说明右边有峰值。

直到区间里面就剩下一个值。

代码

  • 暴力
int findPeakElement(int* nums, int numsLen ) {
    if(numsLen==1)
        return 0;
    if(nums[numsLen-2]<nums[numsLen-1])
        return numsLen-1;
    int i=0;
    while(i<numsLen)
    {
        if(i+1<numsLen&&nums[i]>nums[i+1])
            break;
        i++;
    }
    return i;
}

  • 二分
int findPeakElement(int* nums, int numsLen ) {
    int left=0;
    int right=numsLen-1;
    while(left<right)
    {
        int mid=(left+right)/2;
        if(nums[mid]>nums[mid+1])
            right=mid;
        else
            left=mid+1;
    }
    return left;
}

HJ99自守数

思路

image-20220710165157755

根据这个定义,自守数就是==i*(i-1)%10^m==如果为0,就是自守数。

然而题目对n是有限制的image-20220710165340237,所以我们可以对m进行一一列举。具体的列举看代码。

代码

#include <stdio.h>
#include <math.h>
int main()
{
    int m,n,i;
    int count=0;
    scanf("%d",&n);
    for(i=0;i<=n;i++)
    {
        if(i<10)
            m=1;
        else if(i<100)
            m=2;
        else if(i<1000)
            m=3;
        else if(i<10000)
            m=4;
        else if(i<100000)
            m=5;
        if ((i*(i-1))%(int)pow(10,m)==0) 
            count++;
    }
    printf("%d",count);
    return 0;
}

OR86返回小于N的质数个数

思路

对于任意一个数n,在2~n-1之间出现能被n整除的,就不是素数。

进阶:不是质数一定可以写成两个数相乘的形式。那么我们只需要筛选比开方小的数就可以。

代码

#include <stdio.h>
int main()
{
    int count=0;
    int n;
    scanf("%d",&n);
    for(int i=2;i<n;i++)
    {
        int j=2;
        for(;j<i;j++)
        {
            if(i%j==0)
                break;
        }
        if(i==j)
            count++;
    }
    //另一种写法:注意要包<math.h>
    //for (int i = 2; i < n; i++)
    //{
    //    int j = 2;
    //    for (; j <= (int)sqrt(i); j++)
    //    {
    //        if (i % j == 0)
    //            break;
    //    }
    //    if ((int)sqrt(i) < j)
    //        count++;
    //}
    printf("%d",count);
    return 0;
}