c刷题(三)

程序运行结果 

int a, b, c;
a = 5;
c = ++a;
b = ++c, c++, ++a, a++;
b += a++ + c;
printf("a = %d b = %d c = %d\n", a, b, c);

line3:c=6,a=6;

line4:(逗号表达式,从左向右计算,结果为最后一个表达式)c=8,a=7,b=7(后置)

line5:a=8(更新),+=优先级最低,先计算 a++ +c = 16,b = 16+7 = 23。

line6:a=9,b=23,c=8。

计算二进制中1的个数

前面讲操作符的时候讲了一种计算二进制1的个数的方式,用移位操作符和位操作符进行判断,还有两种方式也可以计算二进制中1的个数。

除余法

整数除以2的本质是将操作数的二进制向右移动一位,等价于>>操作符,而%2则可以判断二进制的最后一位是否为1,因为奇数最低的二进制位必为1.(2^0)

int count_bit(unsigned int m)
{
	int count = 0;
	while (m)
	{
		if (m % 2 == 1)
			count++;
		m /= 2;
	}
	return count;
}

需要注意,计算负数需要传无符号整形,否则会导致计算不准确。 

n&(n-1)法

每进行一次n&n-1的操作都会消去一个1:
n:     10010

n-1: 10001

n&n-1: 10000

n-1:   01111

n&n-1: 00000

可以发现,我们只用了两次就得到了1的个数,通过观察,n-1会将最左边的1变成0,在进行&操作时就会将它变为0,是性能最高的方法。

int count_bit(int m)
{
	int count = 0;
	while (m)
	{ 
		m = m & (m - 1);
		count++;
	}
	return count;
}

 求两个数二进制不同的个数

移位法

移位法没什么好说的,用& , | 或^都可以比较具体二进制位是否相同。

int count_diff_bit(int m, int n)
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if ((m >> i) & 1 != (n >> i) & 1)
			count++;
	}
	return count;
}

异或法

相异为1,再通过刚才我们提到的n&(n-1)法可以直接计算出1的个数就是不同的个数。

int count_diff_bit(int m, int n)
{
	int count = 0;
	int ret = m ^ n;
	while (ret)
	{
		ret = ret & (ret - 1);
		count++;
	}
	return count;
}

相同怎么办?32减去1的个数就行了呗! 

程序运行结果

int i;
int main()
{
    i--;
    if (i > sizeof(i))
    {
        printf(">\n");
    }
    else
    {
        printf("<\n");
    }
	return 0;
}

这里有个隐藏知识点就是全局变量或静态变量未初始化时默认为0局部变量一般初始化为随机值

显然-1是不可能大于一个正数的,但sizeof是无符号类型,用于计算内存大小,在进行比较时算数优先级低的int类型会被转换成unsigned int进行比较,此时-1被当作一个很大的正数来看待,所以会输出'>’。 

上三角判定

上三角矩阵判定_牛客题霸_牛客网

c刷题(三)_第1张图片

先打印矩阵,下三角要遍历所有行,选择遍历列,以对角线为结束条件(j,设置一个开关默认为1,当遇到0时利用goto语句跳出多层循环的特点打印"NO",否则打印1。

	int n;
	scanf("%d", &n);
	int arr[n][n];
	int i = 0;
	for (i = 0; i < n; i++)
	{
		int j = 0;
		for (j = 0; j < n; j++)
		{
			scanf("%d", &arr[i][j]);
		}
	}
	int flag = 1;
	for (i = 0; i < n; i++)
	{
		int j = 0;
		for (j = 0; j < i; j++)
		{
			if (arr[i][j] != 0)
			{
				flag = 0;
				goto end;
			}
		}
	}
end:
	if (flag == 0)
		printf("NO\n");
	else printf("YES\n");

注意没有执行goto end这一语句时仍然会执行end:后的语句。

进制转换

小乐乐与进制转换_牛客题霸_牛客网

c刷题(三)_第2张图片

  • 我们都知道10进制转换为6进制要先进行取余操作:

6%6 = 0

  • 再进行除法:

6/6 = 1        

1做为新的操作数重复以上操作就能得到6进制的形式,可以看出结果是逆序的,我们可以考虑用递归的形式。

 常规做法

#include 
int main()
{
    int n = 0;
    int arr[40] = {0};
    int i = 0;
    scanf("%d", &n);
    while(n)
    {
        arr[i++] = n%6;
        n/=6;
    }
    for(i--; i>=0; i--)
    {
        printf("%d", arr[i]);
    }
    
    return 0;
}

利用数组接收每一个倒序的6进制数,再逆序打印就是对应的结果。

递归

void six_swap(int n)
{
    if(n>0)
    {
        six_swap(n/6);
        printf("%d",n%6);
    }
}
int main()
{
    int a;
    scanf("%d", &a);
    six_swap(a);
}

删除指定数字

序列中删除指定数字_牛客题霸_牛客网

c刷题(三)_第3张图片

思路:遍历数组,将不为删除的数字放入原数组,跳过需要删除的数组。

当然,也可以直接跳过删除的数字打印,算是一种取巧的做法。

#include 

int main()
{
    int num;
    scanf("%d", &num);
    int arr[50] = { 0 };//数组大小0

小乐乐走台阶

小乐乐走台阶_牛客题霸_牛客网

c刷题(三)_第4张图片

两种走法,第一次走一步还有n-1步,第一次走2步还有n-2步,第二次可以选择走一步(n-2 || n-3)或者两步(n-3 || n-4).......

c刷题(三)_第5张图片

以3为例, 每一层有两种选择,每条支路相加就是所有的走法了。

#include 
int Fab_sta(int x)
{
    if (x <= 2)
        return x;
    else
    {
        return Fab_sta(x-1) + Fab_sta(x-2);
    }
}
int main()
{
     int a;
    scanf("%d",&a);
    printf("%d",Fab_sta(a));
    return 0;
}

你可能感兴趣的:(c语言,算法,数据结构)