《算法》第一章部分程序 part 1
▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法
● 代码,二分搜索
- package package01;
- import java.util.Arrays;
- import edu.princeton.cs.algs4.StdRandom;
- public class class01
- {
- public int binarySearch(int [] a, int target) // 非递归实现
- {
- int lp = 0, rp = a.length - 1;
- for(;lp <= rp;) // 含等号的条件,后面修改 lp 和 rp 是使用强的跳跃条件
- {
- int mp = lp + (rp - lp) / 2;
- if (target < a[mp])
- rp = mp - 1; // 不要使用 mp 作为跳跃条件,会导致死循环
- else if (target > a[mp])
- lp = mp + 1;
- else
- return mp;
- }
- return -1;
- }
- public int binarySearchRecursion(int [] a, int target)// 递归实现
- {
- return binarySearchRecursionKernel(a,target,0,a.length-1);
- }
- private int binarySearchRecursionKernel(int [] a, int target, int lp, int rp)
- {
- for(;lp<=rp;)
- {
- int mp = lp + (rp - lp) / 2;
- if (target < a[mp])
- return binarySearchRecursionKernel(a,target,lp,mp - 1);
- else if (target > a[mp])
- return binarySearchRecursionKernel(a,target,mp + 1, rp);
- else
- return mp;
- }
- return -1;
- }
- public static void main(String[] args)
- {
- int N = 10000;
- int [] a = new int [N];
- for(int i=0;i<N;i++)
- a[i] = i;//(int)(StdRandom.uniform()*10000); // 注释部分留作随机检验
- //Arrays.sort(a);
- int target = 7919;//(int)(StdRandom.uniform()*10000);
- int output1 = binarySearch(a,target);
- int output2 = binarySearchRecursion(a,target);
- System.out.printf("\n%d,%d\n",output1,output2);
- return;
- }
- }
● 重复元素二分搜索,包括查找第一次出现、最后一次出现,以及出现多少次
- package package01;
- import java.util.Arrays;
- import edu.princeton.cs.algs4.StdRandom;
- public class class01
- {
- public int binarySearchFirst(int [] a, int target) // 寻找第一个等于键值的目标
- {
- return binarySearchFirstKernel(a, target, 0, a.length-1);
- }
- private int binarySearchFirstKernel(int [] a, int target,int lp,int rp) // 添加起点和终点(两端点都包含),为了能与 Count 函数配合
- {
- for(;lp<=rp;)
- {
- int mp = lp + (rp - lp) / 2;
- if (target < a[mp])
- rp = mp - 1;
- else if (target > a[mp])
- lp = mp + 1;
- else if(mp == 0 || target > a[mp-1]) // target == a[mp],找第一个
- return mp; // a[mp] 就是第一个
- else // a[mp] 前面还有等值的,不能强跳跃,否则可能跨空
- rp = mp;
- }
- return -1;
- }
- public int binarySearchLast(int [] a, int target) // 寻找最后一个等于键值的目标
- {
- return binarySearchLastKernel(a,target, 0, a.length-1);
- }
- private int binarySearchLastKernel(int [] a, int target,int lp, int rp) // 添加起点和终点(两端点都包含)
- {
- for(;lp<=rp;)
- {
- int mp = lp + (rp - lp) / 2;
- if (target < a[mp])
- rp = mp - 1;
- else if (target > a[mp])
- lp = mp + 1;
- else if(mp == a.length-1 || target < a[mp+1]) // target == a[mp],找最后一个
- return mp; // a[mp] 就是第一个
- else // a[mp] 后面还有等值的,不能强跳跃,否则可能跨空
- lp = mp;
- }
- return -1;
- }
- public int binarySearchCount(int [] a, int target) // 寻找等于键值的元素个数
- {
- int lp = 0, rp = a.length-1;
- for(;lp<=rp;)
- {
- int mp = lp + (rp - lp) / 2;
- if (target < a[mp])
- rp = mp - 1;
- else if (target > a[mp])
- lp = mp + 1;
- else // 找到元素后,搜查首个和最后一个进行计数
- return binarySearchLastKernel(a,target,lp,rp) - binarySearchFirstKernel(a,target,lp,rp) + 1;
- }
- return -1;
- }
- public static void main(String[] args)
- {
- int N = 10000;
- int [] a = new int [N];
- for(int i=0;i<N;i++)
- a[i] = i/100;//(int)(StdRandom.uniform()*10000); // 用于随机测试
- //Arrays.sort(a);
- int target = 29;//(int)(StdRandom.uniform()*10000); // 可以检验边界 0,99 等情况
- int output1 = binarySearchFirst(a,target);
- int output2 = binarySearchLast(a,target);
- int output3 = binarySearchCount(a,target);
- System.out.printf("\n%d,%d,%d\n",output1,output2,output3);
- return;
- }
- }
● 数组随机化
- package package01;
- public class class01
- {
- public static void shuffle(Object[] a)
- {
- int n = a.length;
- for (int i = 0; i < n; i++)// 每次在 a[0] ~ a[i] 中随机挑一个 a[r],交换 a[i] 与a[r]
- {
- int r = (int)(Math.random() * (i + 1));
- Object swap = a[r];
- a[r] = a[i];
- a[i] = swap;
- }
- }
- public static void shuffle2(Object[] a)
- {
- int n = a.length;
- for (int i = 0; i < n; i++)// 每次在 a[i] 右边随机挑一个 a[r],交换 a[i] 与a[r]
- {
- int r = i + (int)(Math.random() * (n - i));
- Object swap = a[r];
- a[r] = a[i];
- a[i] = swap;
- }
- }
- public static void main(String[] args)
- {
- String[] a = { "0","1","2","3","4","5","6","7","8","9" };
- class01.shuffle(a);
- for (int i = 0; i < a.length; i++)
- System.out.print(a[i]);
- System.out.print("\n");
- String[] b = { "0","1","2","3","4","5","6","7","8","9" };
- class01.shuffle2(b);
- for (int i = 0; i < a.length; i++)
- System.out.print(b[i]);
- return;
- }
- }
● 计算图连通分量的算法。输入文件第一行是节点数,后面每行是一个连接的两端节点编号,用 java class01 < inputFile.txt 来运行。
- package package01;
- import edu.princeton.cs.algs4.StdIn;
- import edu.princeton.cs.algs4.StdOut;
- public class class01
- {
- private int[] parent; // 节点祖先标记
- private int[] rank; // 树深度,仅根节点有效
- private int count; // 节点数
- public class01(int n)
- {
- count = n;
- parent = new int[n];
- rank = new int[n];
- for (int i = 0; i < n; i++)
- {
- parent[i] = i;
- rank[i] = 1; // 源代码用的是 0
- }
- }
- public int find(int p) // 寻找 p 的根标号
- {
- for (validate(p); p != parent[p]; p = parent[p]);
- return p;
- }
- public int count() // 节点数
- {
- return count;
- }
- public boolean connected(int p, int q) // 判断 p 与 q 是否连通
- {
- return find(p) == find(q);
- }
- public void union(int p, int q) // 合并 p 和 q
- {
- int rootP = find(p);
- int rootQ = find(q);
- if (rootP == rootQ)
- return;
- if (rank[rootP] < rank[rootQ]) // 较小树连接到较大树的树根上,树高按最大值计算
- parent[rootP] = rootQ;
- else if (rank[rootP] > rank[rootQ])
- parent[rootQ] = rootP;
- else // 两树等大,合并后树高增一
- {
- parent[rootQ] = rootP;
- rank[rootP]++;
- }
- count--; // 合并后连接分量减少
- }
- public void union2(int p, int q) // 合并 p 和 q,第二种方法,更快
- {
- int rootP = find(p);
- int rootQ = find(q);
- if (rootP == rootQ)
- return;
- if (rank[rootP] < rank[rootQ])
- {
- parent[rootP] = rootQ;
- rank[rootQ] += rank[rootP]; // 树高按加和计算
- }
- else
- {
- parent[rootQ] = rootP;
- rank[rootP] += rank[rootQ];
- }
- count--;
- }
- private void validate(int p) // 判断输入的 p 是否合法
- {
- if (p < 0 || p >= parent.length)
- throw new IllegalArgumentException("\np = " + p + "is illegal\n");
- }
- public static void main(String[] args)
- {
- int n = StdIn.readInt();
- class01 uf = new class01(n);
- for (; !StdIn.isEmpty();)
- {
- int p = StdIn.readInt();
- int q = StdIn.readInt();
- if (uf.connected(p, q))
- continue;
- uf.union(p, q);
- //StdOut.println(p + " " + q);
- }
- StdOut.println(uf.count() + " components");
- }
- }
《算法》第一章部分程序 part 1的更多相关文章
- 《算法》第一章部分程序 part 2
▶ 书中第一章部分程序,加上自己补充的代码,包括简单的计时器,链表背包迭代器,表达式计算相关 ● 简单的计时器,分别记录墙上时间和 CPU 时间. package package01; import ...
- C语言编程入门之--第一章初识程序
第一章 初识程序 导读:计算机程序无时不刻的影响着人类的生活,现代社会已经离不开程序,程序的作用如此巨大,那么程序到底是什么呢?本章主要讨论程序的概念,唤起读者对程序的兴趣,同时对C语言程序与其它语言 ...
- windows核心编程-第一章 对程序错误的处理
第一章-对程序错误的处理 在开始介绍Microsoft Windows 的特性之前,必须首先了解 Wi n d o w s的各个函数是如何进行错误处理的. 当调用一个Wi n d o w s函数时,它 ...
- 第一章 Python程序语言简介
第一节 Python概述 1. 什么是Python Python是一种 解释型.面向对象.动态数据类型 的高级程序设计语言.由Guido van Rossum与1989年发明,第一个公开发行版本发行于 ...
- ASP.NET本质论第一章网站应用程序学习笔记3-对象化的Http
在.NET环境下,万物皆对象,在HttpRuntime收到请求之后,立即将通过HttpWorkerRequest传递的参数进行分析和分解,创建方便用于网站应用程序处理用的对象,其中主要涉及到两个对象类 ...
- ASP.NET本质论第一章网站应用程序学习笔记2
1.初步走进ASP.NET 上篇笔记我们讲述了服务器监听问题,这篇我们就要讲述具体的请求处理了,ASP.NET所涉及的类大多数定义在System.Web程序集中. 在.NET中,程序集管理的最小逻辑单 ...
- ASP.NET本质论第一章网站应用程序学习笔记1
1.统一资源标示符 1) 格式:协议://主机[.端口号][绝对路径[?参数]],在Http://www.kencery.com/hyl/index/login中,http表示协议的名称,www.ke ...
- 《程序是怎样跑起来的》读书笔记——第一章 对程序员来说CPU是什么
1 程序的运行流程 2 CPU的组成 3 寄存器的主要种类和功能 "程序计数器"--决定程序流程的 4 条件分支和循环机制 4.1 顺序执行 4.2 选择分支 5 函数的调用机制 ...
- 【学习总结】java数据结构和算法-第一章-内容介绍和授课方式
总目录链接 [学习总结]尚硅谷2019java数据结构和算法 github:javaDSA 目录 几个经典算法面试题 算法和数据结构的重要性 几个经典算法面试题 字符串匹配 暴力法:慢 kmp算法:更 ...
随机推荐
- WPF DataGrid 导出Excel
#region Excel导出 private void btnExportExcel_Click(object sender, RoutedEventArgs e) { Export(this.dg ...
- 跟着未名学Office - 熟练使用WORD
目录 第一章.Word之编辑篇. 1 第一节 页面布局... 1 第二节 格式编辑... 1 第三节 表.图.域... 5 第四节 审阅.保护... 7 第五节 *插入对像... 9 第二章.Word ...
- 为什么.net 4.6.1装了却没看到
今天在做SignalR网站,需要在发布到的云服务器安装.net4.6.1 从网上下载了安装包,安装完之后,到Windows文件夹的 Microsoft.NET文件夹中却找不到4.6.1的文件夹. 云服 ...
- problem:vue之数据变更没有触发视图更新问题
前言: 数据变更之后,vue如何渲染dom? 实际场景: 更新数据之后,再设置滚动条的位置为什么设置无效? 为什么将隐藏的元素设置为显示状态之后,读取元素状态读取不到? 改变了对象/数组中的值,页面没 ...
- 《Java并发编程实战》笔记-取消与关闭
1,中断是实现取消的最合理方式.2,对中断操作的正确理解是:它并不会真正地中断一个正在运行的线程,而只是发出中断请求,然后由线程在下一个合适的时刻中断自己.3,区分任务和线程对中断的反应是很重要的4, ...
- 关于Strategy和State设计模式
之前,我在描述我所采用的设计模式时,一直在Strategy和State之间犹豫,略微有些拿捏不准,说哪种设计模式好.结果到最后,会根据自己所想,觉得是State就是State,觉得Strategy就是 ...
- 网站简介-为什么网站的ICO图标更新后,ie浏览器没有更新过来?
为什么网站的ICO图标更新后,ie浏览器没有更新过来? 如何更新本地ico图标? 收藏夹里的网址访问后网站ico小图标怎么不会更新,还是没图标的. 如果制作了一个新的favicon.ico图标,并且已 ...
- hadoop ha环境下的datanode启动报错java.lang.NumberFormatException: For input string: "10m"
hadoop ha环境启动start-dfs.sh的时候datanode启动不了,并且报错. [hadoop@datanode2 ~]$ cat /home/hadoop/hadoop-2.7.3/l ...
- sas share 备忘录
options comamid=tcp;libname payable 'E:\shouen';proc server authenticate=optional id=share1 msgnumbe ...
- mysql 5.7主从库复制设置
先要修改配置文件,重启mysql服务 log-bin= mysql-binlog # 打开二进制日志 ,最好放在不同的硬盘上,减小 IO 消耗 expire_logs_day= # 设置二进制日志保存 ...