Classs2(基尼系数实验)
终于来到了算法的学习,在这里我们先跟着左神,一步步把基础部分的算法过完(也就是入门+必备必须学完)
java创建数组的两种方式
下面是之前记录的一些笔记,我不会把源码全部贴出来,只会贴出来以后需要反复观看的内容,源码直接去code文件夹里面找就行了
1 直接 int []a= new int[5];
2.赋值的方式 int []a=new int []{1,2,3,4,5}
注意不能int []a=new int [5]{1,2,3,4,5}

Arrays.fill(wealth, 100);

这个是把数组里所有元素填满
值都是100
int j = (int) (Math.random() * 5);
这个 ( 随机数的类型 )M ath.random()*n 是从 0 到 n-1 随机抽取一个随机数返回
之后对数器里面也会讲到这个
这个地方之前笔记得有点令人疑惑,我们在这里补充一下
我们把这行代码 int j = (int) (Math.random() * 5); 拆开来,一步一步看你就明白了:
1.Math.random()
这是系统自带的一个生成随机数的方法。它的规则是:生成一个大于等于 0.0 且严格小于 1.0 的小数。
- 它可以是
0.0,可以是0.534,也可以是0.9999,但永远到不了 1.0。
2. *** 5**
接着,把刚才生成的这个随机小数乘以 5。
- 如果刚才生成的是最小的
0.0,乘 5 还是0.0。 - 如果刚才生成的是最大的极限值(比如
0.9999),乘 5 就会无限接近5.0(比如4.9995)。 - 所以这一步做完,结果就变成了一个 0.0 到 4.999... 之间的小数。
3. (int)
这在编程里叫做强制类型转换 。它的作用极其简单粗暴:把小数部分直接砍掉,只保留整数。
- 如果是
0.8,砍掉小数变成0。 - 如果是
2.6,砍掉小数变成2。 - 如果是
4.9995,砍掉小数变成4。
这个地方就很关键了,如果没有砍掉0-n-1 就不对了,就变成了n-1.小数点了,所以因为有了这个的存在才变成了0-n-1了
Math.abs(wealth[i] - wealth[j]);
这个是算绝对值
总结图片里的红字
第一句:"这个...是从 0 到 n-1 随机抽取一个随机数返回" 这里的 n 就是代码里的 5。因为最大只能生成 4.999...,被 (int) 砍掉小数后最大只能是 4。 所以这行代码的最终结果,就是在 0、1、2、3、4 这五个整数里面,随机挑一个赋值给变量 j。这就是红字里说的"0 到 n-1"。
第二句:"之后对数器里面也会讲到这个" "对数器"是学习算法时常用的一个测试技巧。为了验证你写的算法对不对,经常需要让电脑自动生成成千上万个随机的数据(比如随机长度的数组、随机的数字)来测试你的代码。而要生成这些随机数据,就会疯狂用到上面这行代码,这就是为什么教程里说以后还会碰到它。
int[] a = new int[]{2, 3, 1, 4, 5};
Arrays. sort (a) ;
for ( int i = 0 ; i < 5 ; i++) {
System. out .println(a[i]) ;
输出是
1
2
3
4
5
这个是java里面的排序,调用之后,会自动把数组里面的数从小到大排好
今天题目是

算法学习方法:
左神讲了几个点1.复习不要做几个题就回去复习一次,一定要有了不断做新题通过新题来复习,然后有了一定题量(比如刷了700题)之后再整体的大段大段的复习(因为做几个题就频繁往前复习,会影响学习的节奏(什么叫节奏,就是得保证每天都在学新东西而不是复习旧东西),但是切记也不是不复习,一定得复习, 一定要理解什么叫有了大量练习之后,再进行整体复习这句话 )
2.算法不是突击几下就能学会,一定要每天花时间练,像磨刀一样磨。持之以恒力量。不求一天练的多,但很久都不练了,直接断了。但求一年之内,每天都在练习一道。然后付出大量时间,就跟手艺人一样,无它唯手熟尔。
3.要学会和喜欢折腾,只看课,一模一样写出课上代码没有用( 不要仿照它的代码写(我知道他写的很漂亮,但是看了之后你会临时背下来,然后照着它的写了,完全就不知道自己会出现的哪些问题了,就和高中一样,不要照着答案写,不然真的以为自己啥都会) ,自己不看它的代码,只靠自己思路(和课上听到的思路)努力写出来,实在写不动再看一下),要课上学到内容,自己去拿对数器去验证,或者有什么新思路就自己去做实验
class3(二进制和位运算)
二进制的复习

对于有符号数来说,平均分成了负数和非负数 分别有2的31次方个负数 和2的31次方个非负数 然后就是转换了 负数和非负数转换 记住就一个 加1或者减一 再全部取反(包括符号位)
int c = 0b1001110;
int d = 0x4e;
在java里面我们可以直接定义二进制数,比如这里的0b 0x 都没实际的意义,只是定义而已
然后我们还记得int 是32位 long 是48位
讲一下这个相反数: 1.10进制的相反数是直接填负号
2.而2进制的相反数是取反再加1 (但是最小的那个负数取反加1,得到还是本身,就传不过去了,比如四位最小负数是-8对应二进制是1000,取反加一还是1000)
然后我们还发现
求一个数的二进制相反数,和解读一个有符号负数的具体值,在本质上完全是同一个数学操作
- 场景 A(你想把正数变成负数): 你有一个数 X,你需要求它的相反数 -X。根据公式,你的操作是 -X + 1,也就是 取反再加一 。
- 场景 B(你想看懂负数到底是多少): 计算机给你一个负数的补码 -X(比如 1111 1011**),你想知道它的绝对值具体是多少。其实你的大脑在做的事情是**"求这个负数的相反数"** 。既然又是求相反数,再次套用上面的公式,操作依然是(-X) + 1,也就是对这串负数二进制码 取反再加一!
其实就是-13 你看不出来 转成相反数 13你就看出来了
| 是或 $是与 ^是异或(不同是1,相同是0)
然后区分一下&,|和&&,||区别
一个符号是位运算上的或与,两个符号逻辑上或与
一般来说
判断逻辑通常用 &&
做位运算(掩码、取某一位)用 &

这里有一个小细节,也就是左神讲的穿透性,如果A是T的话,接下来B都不会执行了,只有A,B,C全是F,才会一路穿透下去,直到遇到某个变量是T才会停止

但是位运算一定两边都会执行
为什么两者都能判断 True / False?
答案很简单:在计算机底层,根本没有所谓的 true 和 false,只有数字 1****和 0。
当你把布尔值丢给这两种运算符时,它们的计算结果恰好殊途同归:
- 位运算( |****, &****)的角度:单纯的数学计算 位运算把
true当作二进制的1,把false当作二进制的0。 计算true | false,在它眼里就是计算1 | 0(1与0按位或)。根据二进制运算法则,1和0按位或的结果是1。再转换回布尔值,就是true。 - 逻辑运算( ||****, &&****)的角度:条件逻辑判断 逻辑运算就是专门为了处理布尔值设计的。计算
true || false,它的逻辑是"只要有一个为真,结果就是真",所以结果也是true。
二进制设置最精妙的地方就在于 不管是-5加7 还是5+-7 都只要用通一套加法逻辑,而不是最后减法去给定制一套逻辑, 其实总结来说加,减,乘,除,没有自己的逻辑单元,只有位运算的单元,而减乘除都是加法高效的拼接而成的
其实本质上 在CPU的算术逻辑单元(ALU)中,真实的层级是这样的: 位运算构建了加法,加法又构建了其他运算。

左移,就是整个状态往左移动,比如11010往左移动,右边就拿0补

但是负数就得分情况了
如果是正数,就是往右移动,最高位用0补位
但如果是负数,就是往右移动,最高位用符号位补位
printBinary(a);
printBinary(~a);
int e = ~a + 1;
System.out.println(e);
printBinary(e);
~想必都没见过,~这个就是按位取反,再加1才是真正的相反数 所以 ~a + 1=-a
class4(冒泡插入选择排序)
这三个排序被称为三傻排序,在今天基本上只有教学意义,但是插入排序是三傻排序里面最有用的
选择排序有点像我们手里抓了一堆有序的牌,然后新摸了一张牌,再把这张牌排有序
选择排序就是数组坐标0到n-1上选择一个最小值放0坐标,这里是0坐标位置和最小值坐标位置直接交换,和冒泡的两两比较是不一样的,1到n-1上选择一个最小值放1,依次类推,一直结束
冒泡是一直两两比较传递,把最大数冒到最右边
插入是我先认为0-0是有序的,当然有序,因为只有一个数,新来一个数,看看插到哪个位置停下来
下面给出模板
package class004;
public class SelectBubbleInsert {
// 数组中交换i和j位置的数
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
// 选择排序
public static void selectionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int minIndex, i = 0; i < arr.length - 1; i++) {
minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
swap(arr, i, minIndex);
}
}
// 冒泡排序
public static void bubbleSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int end = arr.length - 1; end > 0; end--) {
for (int i = 0; i < end; i++) {
if (arr[i] > arr[i + 1]) {
swap(arr, i, i + 1);
}
}
}
}
// 插入排序
public static void insertionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 1; i < arr.length; i++) {
for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
swap(arr, j, j + 1);
}
}
}
}