1 一个整数,大于0,不用循环和本地变量,按照n,2n,4n,8n的顺序递增,当值大于5000时,把值按照指定顺序输出来。
例:n=1237
则输出为:1237,2474,4948,9896,9896,4948,2474,1237
还得用变量和循环。。。。
void main (){
unsigned int n = 234;
int i = 0;
for(i=0;(1<<i)*n<5000;i++){
printf("%d \n",(1<<i)*n);
}
printf("%d\n",(1<<i)*n);
for(i;i>=0;i--){
printf("%d\n",(1<<i)*n);
}
}
2. 冒泡排序,其实就是两个for循环
int a[] = {1,5,4,3,6,8,99,444,15,89,77};
void main (){
int n = sizeof(a)/sizeof(int);
int i = 0;
int tmp = 0;
int j = 0;
for(j=0;j<n-1;j++){
for(i=0;i<n-1-j;i++){ //注意第二个for循环条件
if(a[i] > a[i+1]){
tmp = a[i];
a[i] = a[i+1];
a[i+1] = tmp;
}
}
}
for(i=0;i<n;i++){
printf("%d\n",a[i]);
}
}
3. 猴子第一天摘下若干个桃子,当即吃掉一半,不过瘾,又多吃了一个,第二天早上又将剩下的桃子吃掉一半,又多吃了一个,以后每天早上都吃掉剩下桃子的一半零一个,到第十天早上的时候,发现只剩下一个桃子了,问猴子第一天摘下多少个桃子?
//sum(n) = 2*(sum(n-1)+1);
int sum (int day){
if(day == 1)
return 1;
return 2*(sum(day-1)+1);
}
void main (){
printf("%d\n",sum(10));
}
4.一个人上台阶可以一次上1个,2个,或者3个,问这个人上n层的台阶,总共有几种走法?
//sum(n) = sum(n-1)+sum(n-2)+sum(n-3);
int sum (int step){
switch (step){
case 1: return 1;
case 2: return 2;
case 3: return 4;
default:break;
}
return sum(step-1)+sum(step-2)+sum(step-3);
}
void main (){
printf("%d\n",sum(5));
}
5. 快速排序法
int a[] = {11,5,13,3,6,8,99,444,15,89,77};
void sort(int * arry,int left,int right){
if(left > right) return ; //这是递归的结束,别忘了。left >= right应该也行
int i = left;
int j = right;
int key = arry[left];
while(i< j){
while(i< j && arry[j]>=key ){
j--;
}
arry[i] = arry[j];
while(i< j && arry[i] <= key){
i++;
}
arry[j] = arry[i];
}
arry[i] = key; //这一轮完后,key左边的都比key小,右边都比key大,所key的位置不用动。
sort(a,left,i-1);
sort(a,i+1,right);
}
void main (){
int k = 0;
sort((int *)a,0,sizeof(a)/sizeof(int)-1);
for(k=0;k<sizeof(a)/sizeof(int);k++){
printf(" %d ",a[k]);
}
}
6.单项链表环 入口点
环链表入口点算法分析:
解法如下:
当p2按照每次2步,p1每次一步的方式走,发现p2和p1重合,确定了单向链表有环路了
接下来,让p2回到链表的头部,重新走,每次步长不是走2了,而是走1,那么当p1和p2再次相遇的时候,就是环路的入口了。
这点可以证明的:
在p2和p1第一次相遇的时候,假定p1走了n步骤,环路的入口是在p步的时候经过的,那么有 p1走的路径: p+c = n;
c为p1和p2相交点,距离环路入口的距离 p2走的路径: p+c+k*L = 2*n;
L为环路的周长,k是整数 显然,如果从p+c点开始,p1再走n步骤的话,还可以回到p+c这个点
同时p2从头开始走的话,经过n步,也会达到p+c这点
显然在这个步骤当中p1和p2只有前p步骤走的路径不同,所以当p1和p2再次重合的时候,必然是在链表的环路入口点上。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Node{
int num;
struct Node *next;
};
struct Node* createCircleList(int n,int circle){
struct Node* list_head = NULL;
struct Node* list1,*list_new;
int i=0;
/*circle must less then n*/
if(circle >= n) return ;
list_head = (struct Node*)malloc(sizeof(struct Node));
list_head->num = 0;
list_head->next = NULL;
list1 = list_head;
for(i=1;i<n;i++){
list_new = (struct Node*)malloc(sizeof(struct Node));
printf("list_new = 0x%x num=%d\n",(unsigned int)list_new,i);
list_new->num = i;
list_new->next = NULL;
list1->next = list_new;
list1 = list_new;
}
/*realize the circle , set list_circle as last list next */
#if 1
list1 = list_head;
while(list1){
if(list1->num == circle){
list_new->next = list1;
break;
}
list1 = list1->next;
}
#endif
return list_head;
}
void freelist(struct Node* list_head){
struct Node* list_freeing = list_head;
struct Node* list_tofree;
while(list_freeing){
list_tofree = list_freeing->next;
list_freeing->next = NULL;
free(list_freeing);
list_freeing = list_tofree;
}
}
//0 1 2 3 4 5 6 7 8 9 10 7 8 9 10 7 8 9 10 7
//0 2 4 6 8 10 8 10 8 10
//1 2 3 4 5 6 7 8 9 10 7 8 9 10
//0 1 2 3 4 5 6 7 8 9 10 6 7 8 9 10 6 7 8 9 10
//0 2 4 6 8 10 7 9 6 8 10
// 1 2 3 4 5 6
int is_circleList(struct Node* list_head){
struct Node* list_step1,*list_step2;
list_step1 = list_step2 = list_head;
while(list_step1 && list_step2 && list_step2->next ){
printf("list step1 =0x%x num=%d\n",list_step1,list_step1->num);
list_step1 = list_step1->next;
list_step2 = list_step2->next->next;
/*equal indicate is a circle list*/
if(list_step1 == list_step2){
/*step2 start walk from origin by one step*/
/*and when meet step2 again is the circle entry*/
list_step2 = list_head;
while(list_step2 != list_step1){
list_step1 = list_step1->next;
list_step2 = list_step2->next;
}
printf("is circle lisnum=%d\n",list_step1->num);
return list_step1->num;
}
}
printf("is not circle \n");
return 0;
}
void main (){
struct Node *list_head = createCircleList(10,4);
struct Node *list_test = list_head;
is_circleList(list_head);
while(list_test){
printf("list num=%d\n",list_test->num);
list_test = list_test->next;
sleep(1);
}
freelist(list_head);
}
7. 二叉树
下面解释转自 https://www.zhihu.com/question/37381035/answer/84584381
二叉树,本质上,是对链表和数组的一个折中。。
比如,我有一个任务,需要输入
10万个数据(32位整数),然后有两个操作:
1.添加(删除)一个整数。
2.询问第x大的数据。
比如,我给你 1, 8, 13, 10(等等一堆数据).......
然后我询问第3大的数据,
然后我插入 18
然后我询问第4大的数据
我再插入 9
我再询问第2大的数据
不停的重复1,2
重复10万次。。
应该如何实现。
你会发现,用有序链表,不行,查找(包括1需要找到对应位置,以及2查找)成本大O(N),但具体这个插入操作成本小O(1)。
用有序数组,查找(2的查找)成本小O(1)。但1的插入操作成本很大O(N)。
所以,我们折中使用排序二叉树(二叉树仅仅作为排序二叉树的基础),查找(包括1需要找到对应位置,以及2查找)成本挺小O(logN)。具体这个插入操作成本也挺小O(logN)。
具体的应用就是由排序二叉树(由于普通排序二叉树可能会有不平衡的情况)引申出来的红黑树(linux中ext3文件系统管理),avl树“windows对进程地址空间的管理”。
8.
typedef struct Node{
int num;
struct Node *next;
}Node;
#define container_of(ptr,type,member) ({\
const typeof(((type *)0)->member) *_mptr = ptr; \
(type *)((char*)(_mptr) - offset_of(type,member));})
#define offset_of(TYPE,MEMBER) ((size_t)&((TYPE*)NULL)->MEMBER)
9. 十进制数 用二进制输出; 二进制字符串表示时,转换成十进制数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
void main (){
char * str1;
char str2[32];
int count,dep,sum,input;
int ret = scanf("%m[0-1] %s %d",&str1,str2,&count); //注意这里scanf使用,第一个时正则匹配,输入不规范时会自动截取
errno = 0;
if ( ret == 3 ){
printf("cyx st1=%s str2=%s count=%d ret=%d\n",str1,str2,count,ret);
}else if(errno != 0){
perror("scanf");
return;
}else{
printf("no match ret=%d\n",ret);
return;
}
/*such as count 98234, convert decimalization to binarization*/
for(int i=31;i--;i>0){
printf("%d",count>>i&0x1);
}
/*such as input "10101010110", convert it to decimalization*/
dep = 1;
sum = 0;
input = count = atoi(str1);
for(int j=1;j<32;j++){
sum+=(count%10)*dep;
count = count/10;
dep=dep*2;
}
printf("\n input=%d sum=%d sum=0x%x\n",input,sum,sum);
}
10. 判断是否为小端
bool is_little (){
union a{
int m;
char n;
}c;
c.n = 1;
// return c.m == 1;
union b{
int m;
int n[2];
}d:
d.n[0] = 10;
d.n[1] = 1;
printf("%d\n",d.m); //大端为0x0a010000 小端为0x10a
}
11. 软连接和硬链接区别
本小结转自简书 链接:https://www.jianshu.com/p/dde6a01c4094
什么是链接?
链接简单说实际上是一种文件共享的方式,是 POSIX 中的概念,主流文件系统都支持链接文件。
它是用来干什么的?
你可以将链接简单地理解为 Windows 中常见的快捷方式(或是 OS X 中的替身),Linux 中常用它来解决一些库版本的问题,通常也会将一些目录层次较深的文件链接到一个更易访问的目录中。在这些用途上,我们通常会使用到软链接(也称符号链接)。
软链接和硬链接的区别是?
下面我们进入正题,来探讨一下软硬两种链接到底有什么区别?
首先,从使用的角度讲,两者没有任何区别,都与正常的文件访问方式一样,支持读写,如果是可执行文件的话也可以直接执行。无论是软链接还是硬链接,文件都保持同步变化
那区别在哪呢?在底层的原理上。
创建软链接 ln -s myfile soft,soft是myfile的软链接
创建硬链接 ln myfile hard, hard时myfile的硬链接
为了解释清楚,我们首先在自己的一个工作目录下创建一个文件,然后对这个文件进行链接的创建:
$ touch myfile && echo "This is a plain text file." > myfile
$ cat myfile
This is a plain text file.
现在我们创建了一个普通地不能再普通的文件了。然后我们对它创建一个硬链接,并查看一下当前目录:
$ ln myfile hard
$ ls -li
25869085 -rw-r--r-- 2 unixzii staff 27 7 8 17:39 hard
25869085 -rw-r--r-- 2 unixzii staff 27 7 8 17:39 myfile
在 ls 结果的最左边一列,是文件的 inode 值,你可以简单把它想成 C 语言中的指针。它指向了物理硬盘的一个区块,事实上文件系统会维护一个引用计数,只要有文件指向这个区块,它就不会从硬盘上消失。
你也看到了,这两个文件就如同一个文件一样,inode 值相同,都指向同一个区块。
然后我们修改一下刚才创建的 hard 链接文件:
$ echo "New line" >> hard
$ cat myfile
This is a plain text file.
New line
可以看到,这两个文件果真就是一个文件。
下面我们看看软链接(也就是符号链接)和它有什么区别。 这时echo ‘new line from soft’ > soft, 其实也会改变myfile
$ ln -s myfile soft
$ ls -li
25869085 -rw-r--r-- 2 unixzii staff 36 7 8 17:45 hard
25869085 -rw-r--r-- 2 unixzii staff 36 7 8 17:45 myfile
25869216 lrwxr-xr-x 1 unixzii staff 6 7 8 17:47 soft -> myfile
诶,你会发现,这个软链接的 inode 竟然不一样啊,并且它的文件属性上也有一个 l 的 flag,这就说明它与之前我们创建的两个文件根本不是一个类型。
下面我们试着删除 myfile 文件,然后分别输出软硬链接的文件内容:
$ rm myfile
$ cat hard
This is a plain text file.
New line
$ cat soft
cat: soft: No such file or directory
之前的硬链接没有丝毫地影响,因为它 inode 所指向的区块由于有一个硬链接在指向它,所以这个区块仍然有效,并且可以访问到。
然而软链接的 inode 所指向的内容实际上是保存了一个绝对路径,当用户访问这个文件时,系统会自动将其替换成其所指的文件路径,然而这个文件已经被删除了,所以自然就会显示无法找到该文件了。
为验证这一猜想,我们再向这个软链接写点东西:
$ echo "Something" >> soft
$ ls
hard myfile soft
可以看到,刚才删除的 myfile 文件竟然又出现了!这就说明,当我们写入访问软链接时,系统自动将其路径替换为其所代表的绝对路径,并直接访问那个路径了。但此时hard 硬链接已经失效了,变成一个独立的文件了,和myfile没有链接关系。
到这里我们其实可以总结一下了:
- 硬链接: 与普通文件没什么不同,
inode都指向同一个文件在硬盘中的区块 - 软链接: 保存了其代表的文件的绝对路径,是另外一种文件,在硬盘上有独立的区块,访问时替换自身路径。
12. 二维数组0,1找连续块
对矩阵做三次扫描, 扫描的次序都是从左到右,从上到下.第一遍将所有为1的元素,依次标一个值,这个值从1开始 例如:
0 0 0 0 0 // 0 0 0 0 0标注成这样
0 1 1 0 0 // 0 1 2 0 0
0 1 0 0 0 // 0 3 0 0 0
0 0 0 1 0 // 0 0 0 4 0
0 0 0 1 0 // 0 0 0 5 0
第二遍 如果 遇到不为0 的元素, 考虑这个元素以及它周围四个元素中,不为0的元素标,求他们的最小值,并将这些元素通标注为这个最小值 像上面,遇到了1 那么将 2和3 标注成 1 。就变成下面这样
0 0 0 0 0
0 1 1 0 0
0 1 0 0 0
0 0 0 4 0
0 0 0 4 0
最后一遍 数一下各种数字的个数,最多的,就是最大全1子块的面积。(注,这样做,结果是连续的全1区域,很可能是不规则的)
本文解析了多个经典编程题目,包括递增序列生成、冒泡排序、猴子吃桃问题等,同时还涉及二叉树、链表环检测、二进制转换等计算机科学核心概念。
918

被折叠的 条评论
为什么被折叠?



