前言
今天分享两道OJ题目,因为解题思路都很简单,重点是要学会算法的优化,以更少的循环次数解决问题。
毕达哥拉斯三元组
初级写法 :输入1000循环500500次
#include<stdio.h>
int main() {
long a, b, c;
long t = 0;
//c^2=a^2+b^2可能溢出
int n = 0;
scanf("%d", &n);
for (a = 0; a < n; a++)
for (b = 0; b < n - a; b++) {
c = n - a - b;
if (a < b && b < c && a * a + b * b == c * c)
printf("%d\n", a * b * c);
t++;
}
printf("%d", t);
return 0;
}
优化后的写法:输入1000循环139276次
#include<stdio.h>
int main()
{
int n, a, b, c, k, i = 0;
long t = 0;
scanf("%d", &n);
//因为c是最大的,不妨令a<b
for (a = 1; a < n / 3; a++)
{
for (b = a + 1, k = n - 2 * a; b < k; b++)
{
c = n - a - b;
t++;
if (a * a + b * b == c * c) {
printf("%d\n", a * b * c);
break;
}
}
if (b < k)
break;
//此处if语句针对的是后续循环,一旦找到便无需继续循环
}
printf("%d", t);
return 0;
}
优化思路:题目中没有明确规定a与b的大小,导致在初级写法中有多次重复循环,降低效率。可以假设a<b<c,并通过a+b+c=n,a,b均小于c给两次for循环中的判定条件进行优化,减少循环次数。
数列问题
有一个数列:1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6……
输入n,输出该数列中的第n项。
本题重点在于对数列形式的判断和转换,可以将其转换为:
1
1 2
1 2 3
1 2 3 4
…………
并由此编写程序
初级写法:输入144,循环143次
思路:a为行,第a行有a个数;b为列;c为架通a与n之间的桥梁
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, a = 1, b = 1, c = 1;
scanf("%d", &n);
int t = 0;
while (c < n)
{
if (b < a)
b++;
else
b = 1, a++;
c++;
t++;
}
printf("%d\n", b);
printf("%d", t);
return 0;
}
优化后的写法:输入144,循环15次
思路:通过求从第1行到 第n位数 所在行及 其上一行 的项数和(sum1和sum0),来判断n所在行数,一步到位。
#include<stdio.h>
int main() {
int n = 0;
scanf("%d", &n);
int j = 1;
int sum0 = 0,sum1 = 0;
int t = 0;
while (n>0) {
sum0 = ((1 + j) * j) / 2;
sum1 = ((2 + j) * (j + 1)) / 2;
//printf("%d\n", sum0);
if (sum0<n && sum1>n)
break;
else if (sum0 == n)
printf("%d", j);
else
j++;
t++;
}
n -= sum0;
printf("%d\n", n);
printf("%d", t);
return 0;
}
总结
目前的OJ题目都以基础算法为主,本文是基于我自身的判断与感受,期待能有路过的高人给予批评指正。