1.
用海伦公式求面积,先判断是不是三角形,不是三角形输出
NaN
,是三角形输出三角形
的面积,小数点后保留两位。海伦公式会给出
输入样例:2
1.0 2.0 3.0
3.0 4.0 5.0
输出样例:
NaN
6.00
判断是否成立,然后利用公式求解面积;
#include<stdio.h>
#include<math.h>
int main(){
int n;
scanf("%d",&n);
while(n--){
double a,b,c,p,area;
scanf("%lf%lf%lf",&a,&b,&c);
if(a+b>c&&a+c>b&&b+c>a){
p=(a+b+c)/2;
area=sqrt(p*(p-a)*(p-b)*(p-c));
printf("%0.2lf\n",area);
}
else
printf("NaN\n");
}
return 0;
}
2.
做一个高考倒计时器,求一年中任意两天差值,输入
N
组数据进行测试时,输出这两天之间的间隔天数,第二个日期总是在比第一个日期要大。
例如,输入:
2
2019 1 1 2019 1 2
2016 1 1 2016 3 1
输出:
2
61
主要几点:日期先后问题,闰年问题
- 年份相同,月份相同,天数不同,天数差值。
- 年份相同,月份不同;
- 分别求出该天是本年的第几天。
- 注意特殊月份二月,设置月份数组,设置判断闰年判断函数,闰年改变二月份数组值,平年数组不变,计算出这一天是这一年的第几天,然后求差值。
- 年份不同;
- 相差一年。先判断每一年的闰年平年情况,值a:前一年全年天数减去思路2.2,值b: 后一年日期是该年的第几天。
- 相差大于一天。在1的基础上,然后将中间相差全年的天数相加(时刻注意判断闰年和平年)。
#include<stdio.h>
int date(int n1,int y1,int r1,int n2,int y2,int r2);
int run_or_ping(int x);
inline int yue_r(int n,int y);
int main()
{
int n1,y1,r1,n2,y2,r2;
printf("请输入第一个较小的年月日,用空格分开\n");
scanf("%04d%02d%02d",&n1,&y1,&r1);
printf("请输入第二个较大的年月日,用空格分开\n");
scanf("%04d%02d%02d",&n2,&y2,&r2);
date(n1,y1,r1,n2,y2,r2);
return 0;
}
int date(int n1,int y1,int r1,int n2,int y2,int r2)
{
int i,j,sum=0,sum1=0;
for(i=n1;i!=n2;i++)
{
if(run_or_ping(i)==1)
sum=sum+366;
else sum=sum+365;
}
if(y1<y2)
for(j=y1;j!=y2;j++)
{
sum=sum+yue_r(n2,j);
}
else
{
for(j=y2;j!=y1;j++)
sum1=sum1+yue_r(n2,j);
sum=sum-sum1;
}
sum=sum+r2-r1+1;
printf("%04d.%02d.%02d~%04d.%02d.%02d相差%d天",n1,y1,r1,n2,y2,r2,sum);
return 0;
}
int run_or_ping(int x)
{
if(x%4==0)
{
if(x%100==0)
if(x%400!=0)
return 0;
return 1;
}
else return 0;
}
int yue_r(int n,int y)
{
if(y==2)
{
if(run_or_ping(n)==1)
return 29;
else return 28;
}
else if(y==4||y==6||y==9||y==11)
return 30;
else return 31;
}
/**
日期格式规定为YYYYMMDD,例如20200709
(1)输入两个日期
(2)以小的日期为底,每次加一天,直到与大的日期相等即可
(2.1)增加一天后,月份,年份都可能会随之变化。针对闰年平年以及大小月天数都一样,采用一个12*2的二维数组列出12月的润平年的天数。
(2.2)当达到月份的天数时,月份加1
(2.3)当达到12个月时,年份加1
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
bool isLeap(int year) {
return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
}
int main() {
//定义好平年和闰年每月的天数
int monthDays[13][2] = {
{0,0},{31,31},{28,29},{30,30},{31,31},{30,30},
{31,31},{30,30},{31,31},{30,30},{31,31},{30,30},
{31,31}
};
int time1, year1, month1, days1;
int time2, year2, month2, days2;
int numbers =1;
// 输入两个日期
cout << "输入两个日期,空格分隔";
cin >> time1 >> time2;
if (time1>time2){
int temp = time1;
time1 = time2;
time2 = temp;
}
//拆解日期,分为年,月,号
year1 = time1 / 10000; month1 = time1 / 100 % 100; days1 = time1 % 100;
year2 = time2 / 10000; month2 = time2 / 100 % 100; days2 = time2 % 100;
//第一个日期 累加到 第二个日期
while (year1 < year2 || month1 < month2 || days1 < days2) {
days1++;// 在第一个日期基础上 加一天
//加一天后,相应的月,年可能也要做一定的变化
if (days1 == monthDays[month1][isLeap(year1)]+1) {//当前号超过当前月最高天数:月份加1,号变成下月的1号
month1++;
days1 = 1;
}
if (month1 == 13) {//月份超过12个月 :年份加1,月份变成下年的1月
year1++;
month1 = 1;
}
numbers++;
}
cout << numbers << endl;
return 0;
}
3.
有一对兔子,从出生后第
3
个月起每个月都生一对兔子,满足
Fibonacci
数列 f(n)=f(n-1)+f(n-2),
1
、
1
、
2
、
3
、
5
、
8
、
13
、
21
、
34
、……小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,输入第 N
个月,输出该月有多少对兔子?
输入样例:
2
3
5
输出样例:
1
2
5
四种解法:递归+动态规划+优化求解+矩阵乘法
解法1:递归
斐波那契数列的标准公式为:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)
根据公式可以直接写出:
int fibonacci1(int n){
if(n<2){
return n;
}
else{
return fibonacci1(n-1)+fibonacci1(n-2);
}
}
时间复杂度:O(2^n)
空间复杂度:O(1)
解法2:动态规划
递归会重复计算大量相同数据,我们用个数组把结果存起来
int Fibonacci(int n) {
vector<int> dp(n+1, 0);
dp[1] = 1;
for (int i=2; i<=n; ++i) {
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
解法3:优化存储
优化:发现计算f[5]的时候只用到了f[4]和f[3], 没有用到f[2]...f[0],所以保存f[2]..f[0]是浪费了空间。只需要用3个变量即可
int Fibonacci(int n) {
if (n == 0 || n == 1) return n;
int a = 0, b = 1, c;
for (int i=2; i<=n; ++i) {
c = a + b;
a = b;
b = c;
}
return c;
}
时间复杂度:O(n)
空间复杂度:O(1)
继续优化:两个变量
//非递归的方法 O(N)
public static int fibonacci2(int n){
if(n<2){
return n;
}
int a=0,b=1;
for(int i=2;i<=n;i++){
b=b+a;//
a=b-a;//
}
return b;
}
时间复杂度:O(n)
空间复杂度:O(1)
解法4:矩阵乘法
4.
求阶乘,求一个数的阶乘,这个数是
1-100
中的一个,提示
32
位会溢出,但是要求输出的结果要保证正确,不能溢出。
输入样例: 25
20
输出样例: 2
120
2432902008176640000
int getFactorial1(int n){// 递归
if(n==1){
return 1;
}
return n*getFactorial1(n-1);
}
/*-------------------------------------------------------------*/
int getFactorial2(int n){// 循环
int result=1;
for(int i=1;i<=n;i++){
result=result*i;
}
return result;
}
5.给定一个括号’(’,’)’,’{’,’}’,’[’,’]’的字符串,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 注意空字符串可被认为是有效字符串,括号里可以包括其他一些字符。
输入样例:
{a}[b](d)
{[}]
输出样例:
Yes
no
用栈实现括号匹配:
依次扫描所有字符,遇到左括号入栈,遇到右括号则弹出栈顶元素检查是否匹配。
匹配失败情况:
①左括号多
②右括号多
③左右括号不匹配
public static boolean isValid1(String s){
Stack<Character> stack=new Stack<>();
if(s==null || s=="")
return false;
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(c=='(' || c=='[' || c=='{' ){
stack.push(c);
}
else if(c!=')' && c!=']' && c!='}'){
continue;
}
else{
if(stack.isEmpty())
return false;
char topChar=stack.pop();
if(c==')' && topChar!='(')
return false;
if(c==']' && topChar!='[')
return false;
if(c=='}' && topChar!='{')
return false;
}
}
//如果遍历完字符串后,栈不为空,则说明括号不匹配
return stack.isEmpty();
}
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
String str=sc.nextLine();
if(isValid1(str)){
System.out.println("匹配成功!") ;
}
else{
System.out.println(" 匹配失败 ");
}
}
首先如果字符串s的长度为奇数的话,直接不符合
这题可以看做是消消乐游戏,匹配则消除,直到全部消除则说明符合条件,没有消除完则说明不符合条件,所以直观的思路就可以使用一个栈来实现。
另外,如何知道消除规则,可以使用一个哈希表来保存消除对应关系。有这样的思路就可以编码了,遍历字符串,如果是左括号(哈希表的key),入栈,如果是右括号,出栈,但是出栈有一个前提是出栈元素能够和当前遍历符号匹配消除,否则直接不符合
class Solution {
public boolean isValid(String s) {
if (s == null || s.length() % 2 != 0) {
return false;
}
//使用一个哈希表保存括号对应关系
Map<Character, Character> map = new HashMap<>();
map.put('(', ')');
map.put('[', ']');
map.put('{', '}');
//遍历字符串,入栈,遇到对应括号,则出栈
Deque<Character> stack = new ArrayDeque<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (map.containsKey(c)) {//如果是左括号,入栈
stack.push(c);
} else {//右括号
//如果当前栈已经是空的,或者栈头元素与该右括号c不匹配,直接返回false
if (stack.isEmpty() || map.get(stack.peek()) != c) {
return false;
}
stack.pop();
}
}
return stack.isEmpty();
}
}