本文已参与「新人创作礼」活动,一起开启掘金创作之路。
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.因为题目说明了都是小写字母
所以我们从新创建一个空间,以字符的大小为下标,出现一次就在以该字符为下标的地方加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自守数
思路
根据这个定义,自守数就是==i*(i-1)%10^m==如果为0,就是自守数。
然而题目对n是有限制的,所以我们可以对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;
}