先声明一下所有代码都是直接手打的 ,没有复制粘贴,有些比较难的算法我就是到网上找视频,跟着他/她敲一遍理解其中的意义所在。

一、归并排序

之前归并排序没有怎么搞懂,这一周又仔仔细细的看了一遍,总结出来的知识。

归并排序实质是用了完全二叉树来设计的,和堆排序有异曲同工之处,接下来看一张图

这是我在知乎上下的一张归并排序的过程图, 可以观察箭头上有分割,也有归并的字样,我当时就很疑惑,为什么归并法会有分割呢?说到这个问题就会涉及到归并的基本思想了。

基本思想

1.分割:将长度为n的序列分割成两个子序列,即n/2;

2.排序:对两个子序列进行排序。

3.归并:将排序好的子序列进行合并。

说完基本思想我们再来看看代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
void merge(int arr[], int tempArr[], int left, int mid, int right);//归并并排序
void merge_sort(int arr[], int n);//归并排序入口
void msort(int arr[], int tempArr[], int left, int right);//分割
main()
{int a[6] = { 14,12,15,13,11,16 };for (int i = 0; i < 6; i++){printf("%d ", a[i]);}printf("\n");merge_sort(a, 6);for (int i = 0; i < 6; i++){printf("%d ", a[i]);}
}
void merge_sort(int arr[], int n)
{int * temp = (int *)malloc(sizeof(int) * n);//动态分配一个//临时数组,为了起到一个中间变量来存放合并并排序的数组msort(arr, temp, 0, n - 1);//第一次是0和最后一个free(temp);
}
void msort(int arr[], int tempArr[], int left, int right)
{int mid = (right+left) / 2;//将原本串分割成两个串if (left < right)//直到做到仅剩一个节点为止{//左分割msort(arr, tempArr, left, mid);//右分割msort(arr, tempArr, mid+1, right);//看到这里如果学过树的遍历的话,就会想到,这是不是就是树的后序遍历merge(arr, tempArr, left, mid, right);}
}
void merge(int arr[], int tempArr[], int left, int mid, int right)
{int lpos,rpos,i=left;//左右字串的指针,准备进行合并lpos = left;rpos = mid + 1;while (lpos <=mid && rpos <=right)//左右字串都还有{if (arr[lpos] < arr[rpos]) { tempArr[i++] = arr[lpos++]; }else { tempArr[i++] = arr[rpos++]; }}while (lpos <= mid)//将剩余的数放入{tempArr[i++] = arr[lpos++];}while (rpos <= right){tempArr[i++] = arr[rpos++];}while(left<=right){arr[left] = tempArr[left];left++;}
}

为了方便理解,我将数组改成和上图一样的数了, 我有三个子函数,分别对应着归并排序法基本思想的三点,msort是对应着“割”,merge是对应着“归并和排序”,merge_sort对应的是整个的初始化,也是入口,在“割”的函数中,如果学过树的话这里也可以运用到树的后序遍历来方便理解,也就是说,你给我一串序列,我先将它不断分割,直到分割到只剩下了一个节点,不能分割为止,我再将它按顺序一个个合并起来,最终成为一个有序的序列。我当时想不清楚为什么需要将它一个个分割成只有一个才进行排序,这样吧我举个例子,首先扯到我们高考成绩,知道两人的成绩高低很简单,比如甲比乙分数高,丙比丁分数高,那我们很容易就得到甲乙丙丁的成绩高低了,直知道这四位同学的成绩高低我们又可以再找四位同学也像这个方案去比,这样我们就得到了八个人的成绩高低,继续这样下去就可以得到全省的成绩高低,你的成绩就会出来了,喔,吉首大学,那太棒了。

学排序不讲空间复杂度和时间复杂度,就是白学。

时间复杂度:O(nlogn)

空间复杂度:O(n+logn)

总结:比较占内存,但效率极高稳定。

二、快速排序

如果你还不会快速排序法的话,一定要去学,快速两个子就可以看出这个算法的牛逼之处了。这个算法被列为20世纪十大算法之一!!还有什么理由不学呢?

还是老样子聊聊基本思想:

基本思想:将当前序列第一个作为关键字,通过一趟排序将当前序列分为两段,左段比关键字小,右段比关键字要大,然后通过递归再将左段和右段通过刚刚的方式又分,最终成为一个有序的数列。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void kuaisu(int a[], int L, int R)
{int right, left,piovet;if (L >= R) return;right = R;left = L;piovet = a[L];//默认第一个为目标量,备份一份,防止被覆盖while (right > left){while (left < right && a[right] >= piovet){right--;}//出来要么是打通关了,要么就是找到一个比piovet小的数了if (left < right) { a[left] = a[right]; left++; }while (left < right && a[left] <= piovet){left++;}//出来要么是打通关了,要么就是找到一个比piovet大的数了if (left < right) { a[right] = a[left]; right--; }if (left >= right) a[left] = piovet;//当left大于right时就表明了,左半区和右半区找完了//那么剩下的那个位置就是目标数的,那么就上皇位a[left]if(L<left)kuaisu(a, L, left - 1);//比目标量小的放在左半区//左半区再进行递归又进行排if(left<R)kuaisu(a, left + 1, R);//比目标量大的放在右半区}
}
int main()
{int a[10],i;for (i = 0; i <10 ; i++){scanf("%d", a + i);}kuaisu(a, 0, 9);for (i = 0; i < 10; i++){printf("%d ", a[i]);}
}
void xuanzefa()
{int i, j, p, t, a[4];printf("\n input 10 numbers:\n");for (i = 0; i < 10; i++)scanf("%d", &a[i]);for (i = 0; i < 10; i++)  //第i轮排序{p = i;for (j = i + 1; j < 10; j++)  //找最小元素if (a[j] < a[p])  p = j;if (i != p) { t = a[i];  a[i] = a[p];  a[p] = t; }  //交换printf("%8d", a[i]);}
}

kuaisu()这个函数做的就是先选取一个关键字,想尽办法将比关键字小的放在左边,将比关键字大的放在右边,接下来我们来说本世纪十大算法的时间复杂度和空间复杂度a

时间复杂度:最好O(nlogn)最差O()

空间复杂度:最好O(logn),最差O(n)

三、bfs(Breadth First Search)层层递进

宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。------百度百科

基本思想和跟dfs的联系和区别

首先它和dfs一样,是一种图的搜索方式,可以发现百度百科中说它思想用在最短路径和最小生成树很多,为什么会应用在这些求最小,最短的问题上呢?,这就和bfs的搜索方式拉上关系了,我们上一周学到了dfs,dfs它是不撞南墙不回头,就是一条路径深入搜索直到没有路走为止,bfs不一样,它属于一种层序遍历,也就是说bfs它先找跟根节点距离为1的所有节点,找完之后再去找距离为2的所有节点,再找距离为3的所有节点......,从小到大依次遍历,所以广度优先遍历一般是求解最短路径问题。

bfs的实现

bfs实现一般是用队列来实现,将根节点入队头,每一次将队头取出,将这个元素所有距离为一的元素,全部入队。

代码实现

我们这里还是走迷宫找出口求最短路径问题的题目。代码逻辑比较简单,其中有很多注释

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <stdbool.h>
struct note
{int x;//x坐标int y;//y坐标int note;//从源节点走到这个节点步数
};
struct note que[2501];//队列,这里也可以用循环队列来节省空间
int head, tail;//head队头,tail队尾
int map[51][51]={0};//地图,用来记录障碍的位置
bool trace[51][51] = { 0 };//判断是否走过
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };//代表四个方向,分别是右下左上
main()
{int c, k,i,j,tx,ty,startx,starty,endx,endy;int flag = 0;//判断是否到出口scanf("%d %d", &startx, &starty);//输入入口scanf("%d %d", &endx, &endy);//输入出口head = tail = 1;que[tail].x = startx;que[tail].y = starty;que[tail].note = 0;//到自己的步数为0
//将源节点入队tail++;//源节点入队后,队尾指针应向后移动一个trace[startx][starty] = true;//将源节点即迷宫入口标记为走过
//初始化完成scanf("%d %d", &c, &k);//输入迷宫大小for (int i = 1; i <= c; i++){for (int j = 1; j <= k; j++)scanf("%d", &map[i][j]);//1代表着障碍,0代表着可以走}while (head < tail)//如果它不是空队,就一直做{for (i = 0; i < 4; i++){tx = que[head].x + dx[i];ty = que[head].y + dy[i];if (tx<1 || tx>k || ty<1 || ty>c)//判断是否越界continue;if (map[tx][ty] == 0 && trace[tx][ty] == 0){//不是障碍,并且没有走过trace[tx][ty] = 1;//将它标记为走过了que[tail].x = tx;que[tail].y = ty;//将该点入队que[tail].note = que[head].note + 1;//到源节点的步数tail++;//入队完成}if (tx == endx && ty == endy)//如果到达出口了就不做了{flag = 1;break;}}if (flag == 1){break;}head++;//相当于出列}printf("%d", que[tail - 1].note);}

队列很重要,对这一道题目!!图的遍历就讲完了呼累啊。

四、滑动窗口

ACM社团考了一个数组问题:螺旋数组,当我写完这个的时候想要将数组的那一块思想给总结一下,我就领出来了一个困惑我比较久的数组的思想,那就是滑动窗口,leetcode上有一道题目叫求最小长度字串,这道题目就是经典的滑动窗口。

题目描述:

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

示例:

输入:s = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

为了体现出优势,我们这边在leetcode上拷贝一个c++的暴力解法

class Solution {
public:int minSubArrayLen(int s, vector<int>& nums) {int result = INT32_MAX; // 最终的结果int sum = 0; // 子序列的数值之和int subLength = 0; // 子序列的长度for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为isum = 0;for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为jsum += nums[j];if (sum >= s) { // 一旦发现子序列和超过了s,更新resultsubLength = j - i + 1; // 取子序列的长度result = result < subLength ? result : subLength;break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break}}}// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列return result == INT32_MAX ? 0 : result;}
};

这个用了两个for循环,不断地去寻找合适地子序列,时间复杂度为O()

我们再来看看滑动窗口

先说说基本思想:
首先要解决三个问题:

1.窗口里面是什么?

2.如何对窗口地起始位置和结束位置进行移动?

1.窗口里面时满足当前和>=s的长度最小的连续子数组

2.当出现>=s了就要窗口起始位置将向前移动(寻找下一个满足>=s的子序列)

3.窗口结束位置就是遍历数组的指针就是for循环里面一直变的j

可以发现滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。

看代码(暑假发布在leetcode上的代码)跟着代码做一遍就会发现它的思想所在了

#define _CRT_SECURE_NO_WARNINGS 1
nt minSubArrayLen(int target, int* nums, int numsSize){//初始化最小长度为INT_MAXint mlenth = INT_MAX;int sum = 0;int left = 0, right = 0;//右边界向右扩展for(; right < numsSize; ++right) {//即结束位置,这就是滑动窗口的精妙,它是结束位置一直在往后移动,而起始位置要通过判定才会移动sum += nums[right];//当sum的值大于等于target时,记录长度,并且收缩左边界,即又到回到<s的情况//就要通过滑动终止位置(j)来继续回到>=s的情况,然后依次类推while(sum >= target) {//注意这里一定要while,因为你要想,若j移动到一个非常大的数,那么我的起始位置就不一定只移动一个,而是很多个int lenth = right - left + 1;mlenth = mlenth < lenth ? mlenth : lenth;sum -= nums[left++];}}//若mlenth存在的话就返回最小长度长度,若不存在就返回0,表示没有该数列return mlenth == INT_MAX ? 0 : mlenth;
}

注意看我的注释,写的很详细哦。

五、大数(+,-,*,/)

这是ACM社的竞赛作业,妈耶,我看到这个提交量,和通过率我就觉得不简单,绝对有坑,我也踩进去了哈哈哈哈

顾名思义,大数就是一个很大的数,是我们口中讲的天文数字一样,很有可能会超过32位和64位,所以我们无法对它进行1直接的加减乘除,那我们应该怎么办呢?用字符串,数组,链表,去模拟加减乘除的计算过程,注意是模拟

先来讲大数加法:

大数加法是最简单的,我们要在脑海里面模拟一下,我们平常做加法的时候是怎么做的,从右往左依次相加,遇到超过10的就进位是不是 。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
main()
{char a[100000], b[100000];int z[10000000], i;int lentha, lenthb,n1,n2,sum;int ys=0;//余数scanf("%s%s", a, b);lentha = strlen(a) - 1;lenthb = strlen(b) - 1;while (lentha >= 0 || lenthb >= 0){n1 = a[lentha--] - '0';//将字符变成数字;n2 = b[lenthb--] - '0';sum = n1 + n2 + ys;ys = sum / 10;z[i++] = sum % 10;}if (ys > 0)//最后一个还要进位{z[i] = ys;}
}

比较简单就直接看代码吧

接下来是大数的减法了 

还是一样,现在脑海里面模拟一下我们小学是怎么算减法的。

是不是发现了加法和减法的区别了,加法是进位,而减法的话就是借位,如果是正好一个大一个小,减起来比较方便,但是一个小数减去一个大数的话那就是还要加一个负号,并且处理起来比较难,所以我们就想,可不可以都换成是大数减小数呢?当然可以,因为1-3=-(3-1),只要在结果上加一个负号就行了,代码实现:

代码以后补,出了一点小问题,不知道怎么解决,先放着,下周来

一名计科生的周总结(week 2)相关推荐

  1. 计科生毕业一年,做了什么?

    计科生毕业一年,做了什么? 毕业之后过得是真的快,又到了记录一年时光的时候了!可以看看一年前的我:大学时期的我 先总结一下自己的成长,这一年里,从毕业开始就很幸运!我做了三件大事: 第一件事:做了一个 ...

  2. 大一下学期转计算机专业来得及吗?——一名双非计科生的自述

    自我介绍 CSDN上的各位,你们好啊!先简单自我介绍一下,我是一名普通二本大学的大一在校生,专业是计算机科学与技术. 我原本学的是电气专业,其实也只是因为没有目标而选择了一个相对来说比较好找工作的专业 ...

  3. 211大二计科生高呼:王侯将相宁有种乎?

    1.我的奇葩高中经历 大家好,我是科科,来自四川农业大学,高中时因为一些原因休学了一年多,后来重新读高中,从高二时转到职高,选择的计算机专业,所以说,我是从高中就开始接触计算机的.在职高的话我奋发图强 ...

  4. 计科1111-1114班第一周讲义、课外作业(截止日期:2014年3月12日23点-周三晚,学委飞信通知同学)

    很高兴能够认识大家,并和大家一起学习<算法设计与分析>课程.根据"学习金字塔"理论,"小组讨论.实践练习.向他人讲授/学以致用"是三种主动学习形式. ...

  5. 清华软院、清华计科、南大计算机、中科院自动化所夏令营保研过程贴

    写在前面 夏令营完回家躺尸了一周,我的天不努力真的太舒服了吧.现在写一下这艰难的保研历程. 开始深入了解保研是在今年三月份开学这样子,没事儿翻翻想去的学校的官网,看看老师,看看导师评价网. 准备保研一 ...

  6. CS全球排名44,复旦计科实力如何?

    1.院校介绍 复旦大学计算机学科国际声誉斐然.2021 年,计算机学科 QS 世界大学排名居全球第 44 位.据 CSRankings 统计,近五年复旦大学在人工智能领域的研究成果排名全球第 17 位 ...

  7. 我的未来该何去何从?双非院校计科院学嵌入式的大四小菜鸡的自我反思...

    这篇文章其实挺早之前就想写的,而且当时就想好了两种心态来写.第一种是小有成就,拿到心满意足的offer来分享一下往昔踩过的坑:第二种就是庸庸碌碌,任重道远.很不幸现在的是第二种心态! 近来看到曾经的同 ...

  8. 学科认知实践报告——我对未来所学专业(计科)的认知

    我得知计算机科学与技术专业,最早可以追溯到高一.高二时,某教育机构发的有关大学专业的资料.资料里介绍了一些热门专业,其中就包含了计科专业. 我高中时很幸运,恰逢浙江省新高考元年,原本文理分科模式被改成 ...

  9. hello world、hello 计科人

    目录 前言 1.从二进制说起 2.C生万物 3.你需要一个帅一点的编译器 4.你需要经过一个异常沮丧的时候 5.你需要学会自行搜索 6.其实开心很重要 后记 前言 大家好,我是一名即将大三的计科菜鸟. ...

最新文章

  1. Ubuntu 14.04 64位上安装wps office软件
  2. 结构体成员数组不定长如何实现
  3. stm32f103zet6linux,stm32f103zet6定时器详解及应用
  4. 傅里叶变换应用——信号调制与解调
  5. java source folder作用_java项目把源码放到folder里,不是source folder,这个java代码还能被调用吗?...
  6. python3.9新特性_Python3.9又更新了:dict内置新功能
  7. 使用静态容器防止并发修改同一对象
  8. 【jQuery学习】—jQuery操作元素位置
  9. 【李宏毅2020 ML/DL】P20-21 Recurrent Neural Network | “Deep and structure is future.“
  10. java连接Neo4j服务器
  11. vue 项目中常见的几个问题
  12. 一份比较详尽的ubuntu下替代windows下的软件列表
  13. python Splinter 12306抢票
  14. ArcGIS中实现空间内插
  15. 【数组】#66 加一
  16. ksh 命令退出状态
  17. 阿里云短信api发送异常
  18. 攻防世界 黑客精神unidbg破解
  19. 新装修的房子怎样知道含不含有甲醛?斐讯悟空M1告诉你
  20. 《炬丰科技-半导体工艺》RCA清洗系统及清洗液自适应预测温度

热门文章

  1. 用命题逻辑推理的方法解决逻辑推理问题。 根据下面的命题,试用逻辑推理方法确定谁是作案者,写出推理过程。
  2. 灰狼算法 c语言 代码,GWO灰狼优化算法
  3. 欧姆龙PLC与DGUSⅡ屏软硬件连接指南
  4. 【百度SD_pro地图学习】
  5. CH583电子价签在线管理方案
  6. 鼠标手势软件MouseGesture v1.0.0.3中文绿色版.rar 相关下载
  7. 【036】Etymonline–英文词源学专业网站
  8. 为文本检测和识别在OCR应用中的突破
  9. S2B2C平台生态图解
  10. ORB-SLAM2的源码阅读(十一):LoopClosing类