1.求一个二进制数中1的个数
思路:二进制数字只有0和1,与1按位与得到了结果也只有0和1,与逻辑有0就出0,全1出1,所以可以叫二进制数字通过右移的方式与1一一的进行按位与,得到1那么你那1位就是1,所以代码如下:
#include#define _CRT_SECURE_NO_WARNINGS int get_one(int num) { int i=0; int count=0; for(i=0;i<32;i++) //共32位往右移31位 if(((num>>i)&1)!=0) { count++; } return count; } int main () { int num=0; int ret =0; scanf("%d",&num); ret=get_one(num); printf("ret=%d",ret); return 0; }
2.打印一个二进制数列的奇数位和偶数位
思路:假设这个数是-1,那么他的二进制序列为32个一,我们叫每个奇数位往后移动两位依次跟1进行与 *** 作,不管你是0还是1,跟1进行 *** 作后都会得到本身那个数,所以偶数位的也可以这么来 *** 作,代码如下:
#includevoid print(int num) { int i=0; int j=0; printf("奇数位为n"); for(i=30;i>=0;i-=2) //奇数位从第1位到31位 { printf("%d ",(num>>i)&1); } printf("n"); printf("偶数位为n"); for(j=31;j>=1;j-=2) //偶数位从第2位到32位 { printf("%d ",(num>>i)&1); } printf("n"); } int main () { int num=0; scanf("%d",&num); print(num); return 0; }
3.给两个int(32位)整数m和n的二进制表达,求其中有多少个位(bit)不同?
思路:最简单的方法无非就是m和n进行异或,相同出0,不同出1,有几个1就有多少个位数不同,所以还是一个求异或后这个数字里边有多少个1,这里不用上述右移动依次按位与的方式来做,这里提供一种新的思路:
假设有下列情况,给n=10,二进制序列为1010,在给n-1=9,二进制序列为1001;两者进行按位与,按位与后的值给n,接着重新将n和新的n-1进行按位与,会发现总会结果变成0,且发现你的n里有几个1,就行几次这种 *** 作。
代码如下:
4.五个跳水选手说:
A选手说:B第二,我第三;
B选手说:我第二,E第四;
C选手说:我第一,D第二;
D选手说:C最后,我第三;
E选手说:我第四,A第一;
比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。
思路:
可以认为真话为1;假话为0;题意说每个人都说对了一半,且每人说了两句话,则可以认为两句话之和为1,要想拿到真正的名次,也就是说所有的话相并为1则才会得到真正的名次,但是这么筛选下来,名次会有很多种情况,因为有重复的,真正的答案一定是只有第1到第5名,名次相乘为120,可以作为最后的筛选条件。代码如下:
#includeint main () { int A=0; int B=0; int C=0; int D=0; int E=0; for (A=1;A<=5;A++) //罗列A的情况 { for (B=1;B<=5;B++)//罗列B的情况 { for (C=1;C<=5;C++)//罗列C的情况 { for(D=1;D<=5;D++)//罗列D的情况 { for(E=1;E<=5;E++)//罗列E的情况 { if(((B==2)+(A==3)==1)&& //真为1 假为0 每个人只说对了一办 则说明每个人说的话加起来为1 ((B==2)+(E==4)==1)&& //全部并起来如果为1 则说明是真正的名次 ((C==1)+(D==2)==1)&& ((C==5)+(D==3)==1)&& ((E==4)+(A==1)==1)) { if(A*B*C*D*E==120) //所有情况都在 有可能名次会重复 所以可以根据名次相乘判断 { printf("A=%d B=%d C=%d D=%d E=%dn",A,B,C,D,E); } } } } } } } return 0; }
5.写一个函数,可以实现右旋字符串中的第K个字符串
假设给一个字符串要求实现abcdefg右转3个字符变成efgabcd;
思路:
下标依次是0到6,即0到元素个数减1,可以考虑先将最右边的字符先交给一临时变量,然后将旁边的字符往右边移动,然后左边位置就空出来了,然后就可将放临时变量的字符放在最左边,这样就实现了右转了。代码如下:
#include#include #include void right_arr(char* arr,int k) { int i=0; char tmp=0; int len=0; assert(arr!=NULL); //定义变量后对指针断言 以防解引用空指针 len=strlen(arr); for (i=0;i 5.写一个函数,可以实现左旋字符串中的第K个字符串
假设给一个字符串要求实现abcdefg左转3个字符变成defgabc;
这个与右转字符串是一个问题,但在这里用另一种方法实现左旋,可以考虑先将你要左旋的字符abc先进行逆序变成cba, 紧接着将逆序右边变成gfed,现在字符串变成cbagfed,然后将整体逆序,变成defgabc,也就是说现在将左旋问题变成了三次逆序问题,对于逆序问题是很简单的,就是将首元素和尾元素进行交换即可,三次逆序可以用一个函数来封装,代码如下:
#include#include #include void reverse(char* left,char *right) //定义left和right两个指针分别指向每次逆序的字符串的首尾元素 { char tmp=0; assert (left); assert (right); //进来断言两个指针不是NULL while (left 6.写一个函数判断一个字符串是否是另一个字符串旋转后的字符串
思路:假设有个串abcdefg,判断一个字符串是否是另一个字符串旋转后的字符串最暴力的方法就是你把所有的旋转后的情况列举出来跟要比较的字符串对比,一样那就满足题意,在这里还有另一种方法,如果将abcdefg后边追加一个abcdefg,即abcdefgabcdefg,这里边已经完全包含了旋转后所有情况,只需要判断你要判断的字符串是否为追加后字符串的子串就行了,是子串那满足题意。这里追加字符串可用strncat 函数,判断子串用strstr函数,这都是库函数。代码如下:
#include#include int is_left_arr(char* str1,char* str2) { int len=0; char* ret=NULL; len=strlen (str1); strncat (str1,str1,6); //自己在自己后边追加本身不能用strcat ret=strstr(str1,str2); if (ret ==NULL) //ret返回空指针说明不是子串 { return 0; } else { return 1; } } int main () { int ret =0; char arr1[30]="abcdef"; char arr2[]="cdefab"; ret=is_left_arr(arr1,arr2); if (ret ==1) { printf ("Yn"); } else { printf("Nn"); } return 0; } 7.在杨氏矩阵中找一个数,杨氏矩阵是每一行元素递增,每一列元素递增
思路:
根据杨氏矩阵的定义,有右上角和左下角的元素是非常特殊的,比如右上角的元素是一行中最大的元素,且是一列中最小的元素,假设矩阵是
1 2 3
4 5 6
7 8 9 查找5,可发现5比右上角的元素3大,则说明不在第一行,所以第一行元素就可以直接不考虑了,现在右上角的元素是6,6>5,且6是所在列的最小元素,则说明6所在的列也没有5,所以往左边走,类似的,直到你行下标比行数减1还要小或者等于并且列下标大于等于0了就查找结束了。代码如下:
#includeint FindNum(int arr[3][3],int k,int row,int col) { int x=0; int y=col -1;//右上角元素的下标为列-1 while (x<=row-1&& y>=0) { if (arr[x][y]>k) { y--; } else if (arr[x][y] 结束:
仅代表自己学完做练习的一点点小总结,由于知识的局限性一定存在很多问题,希望各位大佬勿喷,感谢!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)