这篇文章主要是想向大家说其实力扣的好多题的解法都是很像的,我虽然刷的少,但是在这些题上都看到了熟悉的影子,就是想给大家打打鸡血吧。
题单一::202.力扣快乐数
解题思路:
快乐数就是不断求它的平方和,当某个平方和等于1时则是快乐数;
那你可能会问,一个数不断求平方和它总有可能在某一个时刻等于1吧,显然这个想法是不对的(不然为什么有快乐数的概念);
那我又要问为什么会不是快乐数呐?相信你肯定猜到了,当平方数之间产生某种循环的时候就不会得到1,解题思路就来了!
解题代码:
方法一:快慢指针法
如果不知道什么是快慢指针?传送门:快慢指针
这个快慢指针和链表那里判断环形链表有点像,因为本题也是可以通过判断是否有循环来解决
有人称作他为隐式链表,它们之间的next在此题用fun(n),该函数用来求每一十进制位的平方和来代替(next是连接两个结点的枢纽,其实fun(n)函数也是本身和他平方和数之间的枢纽)
如果有循环就是就是说明这个说明快指针和慢指针在某一个点会相遇
如果没有循环(平方和最后可以为1),快指针就会遇到1停下来
代码:
#include<stdio.h>
#include<math.h>
int fun(int n)
{
int a[10] = { 0 };
int len = 0;
while (n)
{
a[len++] = n % 10;
n /= 10;
}
int ret = 0;
while (len--)
{
ret += (int)pow(a[len], 2);//强制类型转换,因为pow数学函数的返回值默认为double类型
}
return ret;
}
int main()
{
int n = 0;
scanf("%d", &n);
int fast = n;
int slow = n;
while (fast != 1)//如果为1,就没有环,是快乐数
{
fast = fun(fast);
fast = fun(fast);
slow = fun(slow);
if (slow == fast)//如果相遇,就有环
{
printf("该数不是快乐数\n");
return 0;
}
}
printf("该数是快乐数\n");
return 0;
}
方法二:数学大佬
通过数学方法找到这些造成循环的数,也就是 上面环上的平方和数,但是这种方法知道就好,不用深究。
循环的数:4--->16---->37----->58----->89------->145------->42------->20 ------>4
如果有循环就是就是平方和为以上8个数
如果没有循环(平方和最后可以为1),快指针就会遇到1停下来
代码:
#include<stdio.h>
#include<math.h>
int fun(int n)
{
int a[10] = { 0 };
int len = 0;
while (n)
{
a[len++] = n % 10;
n /= 10;
}
int ret = 0;
while (len--)
{
ret += (int)pow(a[len], 2);
}
return ret;
}
int main()
{
int n = 0;
scanf("%d", &n);
int a[8] = { 4,16,37,58,89,145,42,20 };
while (fun(n) != 1)
{
for (int i = 0; i < 8; i++)
{
if (fun(n) == a[i])
{
printf("该数不是快乐数\n");
return 0;
}
}
n = fun(n);
}
printf("该数是快乐数\n");
return 0;
}
我想说:
快慢指针其实使用范围不局限于单链表,隐式链表同样适用。
题单二:
题目描述:
解题思路:
字母异位词也就是两个字符串所包含的英文字母和其字母个数都是相同的;
说实话,刚开始我还打算给字母排序然后一一比较,显然这行不通
那么突然我就想到之前我在力扣上做过的一题并写了博客:剑指offer之数组中的重复元素
剑指offer之数组中的重复元素这题讲的是找出一个数组里重复的元素
其中我给的第二种方法:临时数组法,通过让数组元素作为一个临时数组的下标产生一种映射关系,然后遍历数组,以数组元素值为下标的临时数组就对应+1来计数,遍历完后通过临时数组哪些元素为2,就对应返回这个临时数组的下标即可.
举个例子:
本题同样可以使用这种方法,因为题目说字母都是小写字母,那么对应开辟两个临时数组,每一个临时数组元素个数就定位26,遍历完两个数组后就产生两种映射关系,然后两个临时数组元素值比较大小就代表字符出现的个数.
代码:
#include<stdio.h>
int main()
{
char str1[] = "hello";
char str2[] = "lolex";
int len1 = strlen(str1);
int len2 = strlen(str2);
//如果长度都不相等,那一定不是有效的字母异位词
if (len1 != len2)
{
printf("否\n");
return 0;
}
//开辟两个临时数组
int temp1[26] = { 0 };
int temp2[26] = { 0 };
//产生映射关系
for (int i = 0; i < len1; i++)
{
temp1[str1[i]-'a']++;
}
for (int i = 0; i < len2; i++)
{
temp2[str2[i]-'a']++;
}
//比较是否有该字符元素且个数是否相等
for (int j = 0; j < 26; j++)
{
if (temp1[j] != temp2[j])
{
printf("否\n");
return 0;
}
}
printf("是\n");
return 0;
}
题单三:
题目描述:434. 【力扣】字符串中的单词数
题解思路:
我猜你之前肯定和我一样,打算计算空格的个数来得出单词的个数,但是每一个单词的前后可能有空格,也可能只有一个空格,所以这个思路根本行不通!再者说可以多个空格连在一起组成“空格串”
其实我们可以遍历一遍字符串,以空格结尾和字符串的开头的连接的个数作为单词的个数
#include<stdio.h>
#include<string.h>
int main()
{
char str[] = " can you do it? ";
int len = strlen(str);
int count = 0;//求单词个数
for (int i = 0; i<len; i++)
{
while (i < len && str[i] == ' ')
{
i++;
}
if(i<len)
count++;
while (i < len && str[i] != ' ')
{
i++;
}
}
printf("%d\t", count);
}
或者这样:
#include<stdio.h>
#include<string.h>
int main()
{
char str[] = " can you do it? ";
int len = strlen(str);
int count = 0;//求单词个数
for (int i = 1; i < len; i++)//从1开始
{
if ((str[i] == ' ' || str[i] == '\0') && str[i - 1] != ' ')
count++;
}
printf("%d\t", count);
}