算法试题——每日一练

求整数x的平方根

给定一个非负整数,求它的平方根,只要整数部分。
第一次通过的代码:

int mySqrt(int x){
    long int low,high,mid,t;
    low = 0;
    high = x;
    while(low <= high)
    {
        if(x == 1)
            break;
        else
        {   
            mid = (low + high) / 2;
            if((mid * mid) <= x)
             {
                 t = mid + 1;
                 while((t * t) <= x)
                {
                    t++;
                }
                return (t - 1);
             }
            else
                high = mid;
        }
    }
    return x;
}

后面再看了一下,变量 l o w low low一直是0,可有可无,没有起到什么作用😑,可以把它删除,但进而一系列的代码也要做相应的改动。且当数据很大时, m i d ∗ m i d mid * mid midmid很有可能会发生溢出,因此上面代码我用的长整型变量,这里也可以在那个小于号的左右两边同时除以一个 m i d mid mid,就变成 m i d ≤ x / m i d mid\leq x / mid midx/mid了。

int mySqrt(int x)
{
    int g;
    if(x <= 1)
    	return x;
	g = x / 2;
    //对应上面的while(low <= high)
    while(g > x / g)
    {
        g /= 2;
    }
    //对应上面的while(t * t <= x)
    while(g <= x / g)
    {
        g++;
    }
    return (g - 1);
}

爬楼梯

假设要爬到第 n n n个台阶上,一次只能爬1阶或者2阶,那么第爬到第 n n n阶上有多少种爬法?例如:
1阶:
1
2阶:
1+1
2
3阶:
1+1+1
1+2
2+1
4阶:
1+1+1+1
2+1+1
1+2+1
1+1+2
2+2

首先我看到这个题目的时候第一个想法就是直接去敲代码,在代码里思考。但是这样的题目一般我们都可以先用数学的思想去做,先找找规律,理清自己的思路,再上手代码。

那么,这个题目的思路其实很简单,自己多列几阶就能看出来,自第三阶开始,每阶的爬法都是前两种之和。

这样,我首先就想到了用函数递归就可以实现。

#include <stdio.h>
int climbStairs(int n)
{
	if(n <= 3)
		return n;
	else
		return ((climbStairs(n - 1) + climbStairs(n - 2));
}
int main()
{
	int a,b;
	printf("Please input the number of the stairs:");
	scanf("%d",&a);
	b = climbStairs(a);
	printf("%d",b);
	return 0;
}

通过递归,n较小的时候还好,n一旦稍微大一点,运行的速度就慢下来了,因为它要不停地去调用函数,这就使非常耗费时间,于是我又开始考虑用迭代去实现,从而避免调用函数。

#include <stdio.h>
int climbStairs(int n){
	int a,b,c;
	if(n <= 3)
		return n;
	else
	{
		a = 2;
		b = 3;
	}
	for(int i = 4 ; i <= n ; i++)
	{
		c = a + b;
		a = b;
		b = c;
	}
	return c;
}

int main()
{
	int a,b;
	printf("Please input the number of the stairs:");
	scanf("%d",&a);
	b = climbStairs(a);
	printf("%d",b);
	return 0;
}

删除有序数组中的重复项

给定一个有序数组,删除它里面的重复项,也就是每种数字只有一个。并返回删除重复数字后数组的长度。假如返回的数组长度为k,那么该数组中前k个元素全都是不重复的数字。
例如,对于 [ 1 , 1 , 1 , 2 , 2 , 3 ] [1,1,1,2,2,3] [1,1,1,2,2,3],返回3,且输出为 [ 1 , 2 , 3 ] [1,2,3] [1,2,3]。(只能说输出是这个顺序,并不一定要有“ [ ] ”。)

我首先想到的就是先找到重复的数字,再把它们删除,删除后又将后面的元素移到前面来,进而又继续找下一个重复的数字。但是写代码的时候总是有错误,也仔细把数据带进去看了,很是麻烦,😢。最后实在不行了就去欣赏了一下其他人的答法,发现好多人都是用的指针法。它们并没有把后面的数字全部都移到前面去,而是巧妙地用后面的元素将重复的元素覆盖。最后前k个元素自然就是全都不重复的了。

#include <stdio.h>
int removeDuplicates(int* nums, int numsSize){
    int i,n;
    n = 0;
    for(i = 1 ; i < numsSize ; i++)
    {
        if(nums[n] != nums[i])
        {
            n++;
            nums[n] = nums[i];
        }
    }
    return (n + 1);
}

int main()
{
	int a[] = {1,1,1,2,2,3},b = 6,c;
	c = removeDuplicates(a,b);
	for(int i = 0 ; i < c ; i++)
		printf("%d ",a[i]);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值